Skip to content

Commit 37da5d0

Browse files
committed
added some coding exercise challenges
1 parent 2ab554a commit 37da5d0

10 files changed

+358
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
2+
3+
const result = numbers
4+
.filter(num => num % 2 === 0) // [2, 4, 6, 8, 10]
5+
.map(num => num * 2) // [4, 8, 12, 16, 20]
6+
.reduce((sum, num) => sum + num, 0); // 60
7+
8+
console.log(result); // 60
9+
10+
/**
11+
* Explanation:
12+
*
13+
* This demonstrates method chaining with array methods in JavaScript.
14+
*
15+
* 1. filter() creates a new array with elements that pass the test.
16+
* Here, it keeps only even numbers: [2, 4, 6, 8, 10]
17+
*
18+
* 2. map() creates a new array by transforming each element.
19+
* Here, it doubles each number: [4, 8, 12, 16, 20]
20+
*
21+
* 3. reduce() reduces the array to a single value.
22+
* Here, it sums all numbers: 4 + 8 + 12 + 16 + 20 = 60
23+
*
24+
* 4. Each method returns a new array (except reduce), allowing chaining.
25+
*
26+
* 5. This functional programming style is concise and readable.
27+
*
28+
* Note: Each method creates a new array, so for large datasets, consider
29+
* performance implications. A single loop might be more efficient.
30+
*/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
async function fetchData() {
2+
throw new Error('Network error');
3+
}
4+
5+
async function getData() {
6+
try {
7+
const data = await fetchData();
8+
console.log(data);
9+
return data;
10+
} catch (error) {
11+
console.log('Caught:', error.message);
12+
return null;
13+
}
14+
}
15+
16+
getData().then(result => {
17+
console.log('Result:', result);
18+
});
19+
20+
// Output:
21+
// Caught: Network error
22+
// Result: null
23+
24+
/**
25+
* Explanation:
26+
*
27+
* This demonstrates error handling with async/await in JavaScript.
28+
*
29+
* 1. fetchData() is an async function that throws an error.
30+
*
31+
* 2. In getData(), we use try/catch to handle errors from await fetchData().
32+
*
33+
* 3. When fetchData() throws an error, it's caught by the catch block,
34+
* which logs the error message and returns null.
35+
*
36+
* 4. The .then() receives the return value from getData(), which is null
37+
* because the error was caught and handled.
38+
*
39+
* 5. Without try/catch, the error would propagate and could be caught
40+
* with .catch() on the promise chain.
41+
*/

coding-exercise/closure-counter.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
function createCounter() {
2+
let count = 0;
3+
return function() {
4+
count++;
5+
return count;
6+
};
7+
}
8+
9+
const counter1 = createCounter();
10+
const counter2 = createCounter();
11+
12+
console.log(counter1()); // 1
13+
console.log(counter1()); // 2
14+
console.log(counter2()); // 1
15+
console.log(counter1()); // 3
16+
17+
/**
18+
* Explanation:
19+
*
20+
* This demonstrates closure behavior in JavaScript.
21+
*
22+
* 1. createCounter() returns a function that has access to the 'count' variable
23+
* from its outer scope, even after createCounter() has finished executing.
24+
*
25+
* 2. Each call to createCounter() creates a new closure with its own 'count' variable.
26+
* So counter1 and counter2 maintain separate counts.
27+
*
28+
* 3. counter1() increments its own count: 1, 2, 3
29+
* counter2() has its own separate count: 1
30+
*
31+
* This is a classic example of how closures can be used to create private variables.
32+
*/
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function displayUser({ name = 'Guest', age = 18, country } = {}) {
2+
console.log(`Name: ${name}, Age: ${age}, Country: ${country}`);
3+
}
4+
5+
displayUser({ name: 'John', age: 25, country: 'USA' });
6+
// Name: John, Age: 25, Country: USA
7+
8+
displayUser({ name: 'Alice' });
9+
// Name: Alice, Age: 18, Country: undefined
10+
11+
displayUser();
12+
// Name: Guest, Age: 18, Country: undefined
13+
14+
/**
15+
* Explanation:
16+
*
17+
* This demonstrates destructuring with default values in JavaScript.
18+
*
19+
* 1. The function parameter uses object destructuring to extract properties.
20+
*
21+
* 2. Default values (name = 'Guest', age = 18) are provided for some properties.
22+
* If these properties are not passed or are undefined, the defaults are used.
23+
*
24+
* 3. The = {} at the end provides a default empty object if no argument is passed,
25+
* preventing a TypeError when trying to destructure undefined.
26+
*
27+
* 4. country has no default, so it remains undefined if not provided.
28+
*
29+
* This pattern is useful for functions with optional parameters.
30+
*/
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
const name = 'Alice';
2+
const age = 30;
3+
4+
// Old way
5+
const user1 = {
6+
name: name,
7+
age: age
8+
};
9+
10+
// ES6 shorthand
11+
const user2 = {
12+
name,
13+
age
14+
};
15+
16+
console.log(user1); // { name: 'Alice', age: 30 }
17+
console.log(user2); // { name: 'Alice', age: 30 }
18+
console.log(user1.name === user2.name); // true
19+
20+
/**
21+
* Explanation:
22+
*
23+
* This demonstrates ES6 object property shorthand syntax.
24+
*
25+
* 1. When creating an object, if the property name matches the variable name,
26+
* you can use the shorthand syntax.
27+
*
28+
* 2. { name, age } is equivalent to { name: name, age: age }
29+
*
30+
* 3. This makes code more concise and readable, especially when dealing with
31+
* many properties.
32+
*
33+
* 4. Both user1 and user2 are functionally identical.
34+
*
35+
* This is commonly used in modern JavaScript, especially with destructuring
36+
* and when returning objects from functions.
37+
*/
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const promise1 = Promise.resolve(3);
2+
const promise2 = new Promise((resolve) => setTimeout(() => resolve('foo'), 100));
3+
const promise3 = Promise.reject('Error occurred');
4+
const promise4 = Promise.resolve(42);
5+
6+
Promise.all([promise1, promise2, promise4])
7+
.then(values => {
8+
console.log(values); // [3, 'foo', 42]
9+
})
10+
.catch(error => {
11+
console.log('Caught:', error);
12+
});
13+
14+
Promise.all([promise1, promise2, promise3, promise4])
15+
.then(values => {
16+
console.log(values); // This won't execute
17+
})
18+
.catch(error => {
19+
console.log('Caught:', error); // Caught: Error occurred
20+
});
21+
22+
/**
23+
* Explanation:
24+
*
25+
* This demonstrates Promise.all() behavior in JavaScript.
26+
*
27+
* 1. Promise.all() takes an array of promises and returns a single promise.
28+
*
29+
* 2. If ALL promises resolve, Promise.all() resolves with an array of all
30+
* resolved values, in the same order as the input promises.
31+
*
32+
* 3. If ANY promise rejects, Promise.all() immediately rejects with the
33+
* reason of the first promise that rejected. Other promises are ignored.
34+
*
35+
* 4. In the first example, all three promises resolve, so we get [3, 'foo', 42].
36+
*
37+
* 5. In the second example, promise3 rejects, so Promise.all() rejects
38+
* immediately with 'Error occurred', even though promise1 and promise4
39+
* would have resolved.
40+
*
41+
* 6. Promise.all() waits for all promises to settle (resolve or reject).
42+
*
43+
* Use Promise.allSettled() if you want to wait for all promises regardless
44+
* of whether they resolve or reject.
45+
*/

coding-exercise/prototype-chain.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function Animal(name) {
2+
this.name = name;
3+
}
4+
5+
Animal.prototype.speak = function() {
6+
console.log(this.name + ' makes a sound.');
7+
};
8+
9+
function Dog(name) {
10+
Animal.call(this, name);
11+
}
12+
13+
Dog.prototype = Object.create(Animal.prototype);
14+
Dog.prototype.constructor = Dog;
15+
16+
Dog.prototype.speak = function() {
17+
console.log(this.name + ' barks.');
18+
};
19+
20+
const dog = new Dog('Rex');
21+
dog.speak(); // Rex barks.
22+
console.log(dog instanceof Dog); // true
23+
console.log(dog instanceof Animal); // true
24+
25+
/**
26+
* Explanation:
27+
*
28+
* This demonstrates prototypal inheritance in JavaScript.
29+
*
30+
* 1. Dog inherits from Animal using Object.create(Animal.prototype).
31+
*
32+
* 2. Animal.call(this, name) calls the Animal constructor in the context of Dog,
33+
* allowing Dog to inherit Animal's properties.
34+
*
35+
* 3. Dog.prototype.constructor = Dog resets the constructor property after
36+
* overwriting the prototype.
37+
*
38+
* 4. Dog overrides the speak method from Animal.
39+
*
40+
* 5. dog instanceof checks the prototype chain, so dog is an instance of both
41+
* Dog and Animal.
42+
*/
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const obj1 = { a: 1, b: 2 };
2+
const obj2 = { b: 3, c: 4 };
3+
const obj3 = { ...obj1, ...obj2 };
4+
5+
console.log(obj3); // { a: 1, b: 3, c: 4 }
6+
7+
const original = { x: 1, y: { z: 2 } };
8+
const copy = { ...original };
9+
10+
copy.x = 10;
11+
copy.y.z = 20;
12+
13+
console.log(original.x); // 1
14+
console.log(original.y.z); // 20
15+
16+
/**
17+
* Explanation:
18+
*
19+
* This demonstrates the spread operator with objects in JavaScript.
20+
*
21+
* 1. The spread operator (...) copies properties from one object to another.
22+
*
23+
* 2. When spreading multiple objects with the same property (like 'b'),
24+
* the last one wins. So obj2.b (3) overwrites obj1.b (2).
25+
*
26+
* 3. The spread operator creates a SHALLOW copy, not a deep copy.
27+
*
28+
* 4. Primitive values (like x) are copied by value, so changing copy.x
29+
* doesn't affect original.x.
30+
*
31+
* 5. Nested objects (like y) are copied by reference, so changing copy.y.z
32+
* DOES affect original.y.z.
33+
*
34+
* For deep copying, you need JSON.parse(JSON.stringify()) or a library like lodash.
35+
*/
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
console.log(varVariable); // undefined
2+
console.log(letVariable); // ReferenceError: Cannot access 'letVariable' before initialization
3+
4+
var varVariable = 'I am var';
5+
let letVariable = 'I am let';
6+
7+
/**
8+
* Explanation:
9+
*
10+
* This demonstrates the Temporal Dead Zone (TDZ) in JavaScript.
11+
*
12+
* 1. Variables declared with 'var' are hoisted to the top of their scope
13+
* and initialized with 'undefined'. So accessing varVariable before
14+
* its declaration returns undefined (no error).
15+
*
16+
* 2. Variables declared with 'let' and 'const' are also hoisted, but they
17+
* are NOT initialized. They remain in the "temporal dead zone" from the
18+
* start of the block until the declaration is executed.
19+
*
20+
* 3. Accessing letVariable before its declaration throws a ReferenceError
21+
* because it's in the TDZ.
22+
*
23+
* 4. The TDZ exists to catch programming errors and make code more predictable.
24+
*
25+
* 5. The same behavior applies to 'const' declarations.
26+
*
27+
* Best practice: Always declare variables at the top of their scope.
28+
*/
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
console.log([] == false); // true
2+
console.log([] === false); // false
3+
console.log('' == 0); // true
4+
console.log('' === 0); // false
5+
console.log(null == undefined); // true
6+
console.log(null === undefined); // false
7+
8+
/**
9+
* Explanation:
10+
*
11+
* This demonstrates type coercion with == vs === in JavaScript.
12+
*
13+
* 1. == (loose equality) performs type coercion before comparison.
14+
* === (strict equality) does NOT perform type coercion.
15+
*
16+
* 2. [] == false:
17+
* - [] is converted to a primitive: [].toString() = ''
18+
* - false is converted to a number: 0
19+
* - '' is converted to a number: 0
20+
* - 0 == 0 is true
21+
*
22+
* 3. [] === false:
23+
* - No coercion, different types (object vs boolean), so false
24+
*
25+
* 4. '' == 0:
26+
* - '' is coerced to 0, so 0 == 0 is true
27+
*
28+
* 5. '' === 0:
29+
* - Different types (string vs number), so false
30+
*
31+
* 6. null == undefined:
32+
* - Special case in JavaScript, they are loosely equal
33+
*
34+
* 7. null === undefined:
35+
* - Different types, so false
36+
*
37+
* Best practice: Use === to avoid unexpected type coercion bugs.
38+
*/

0 commit comments

Comments
 (0)