Skip to content

Commit ec6e10f

Browse files
Merge branch 'master' into javascript
2 parents 18ab0d4 + dee3d12 commit ec6e10f

File tree

4 files changed

+187
-21
lines changed

4 files changed

+187
-21
lines changed

README.md

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,11 @@
506506
| 475 | [What are shadowing and illegal shadowing?](#what-are-shadowing-and-illegal-shadowing) |
507507
| 476 | [Why is it important to remove event listeners after use?](#why-is-it-important-to-remove-event-listeners-after-use) |
508508
| 477 | [What is structuredClone and how is it used for deep copying objects?](#what-is-structuredclone-and-how-is-it-used-for-deep-copying-objects) |
509+
509510
| 477 | [What is the difference btw == & === in java script?](#what-is-structuredclone-operators) |
510511

512+
| 478 | [What is the difference between const and Object.freeze](#what-is-the-difference-between-const-and-objectfreeze) |
513+
511514
<!-- TOC_END -->
512515

513516
<!-- QUESTIONS_START -->
@@ -9554,36 +9557,36 @@ Common use cases and benefits:
95549557

95559558
**[⬆ Back to Top](#table-of-contents)**
95569559

9557-
479. ### What is the purpose of the at() method
9560+
479. ### What is the purpose of the at() method
95589561

9559-
The `at()` method takes an integer value and returns the item at that index, allowing for positive and negative integers. Negative integers count back from the last item in the array or string.
9562+
The `at()` method takes an integer value and returns the item at that index, allowing for positive and negative integers.
9563+
Negative integers count back from the last item.
95609564

9561-
Prior to this method, accessing the last element of an array required using array[array.length - 1]. The at() method makes this much cleaner and supports both **Arrays** and **Strings**.
9565+
Prior to this method, accessing the last element of an array required using array[array.length - 1].
9566+
The at() method makes this much cleaner and supports both **Arrays** and **Strings**.
95629567

9563-
*Key Features:*
9564-
1. *Positive Index:* Works the same as square bracket notation [].
9565-
2. *Negative Index:* Counts from the end of the array (e.g., -1 is the last element).
9568+
**Key Features:**
9569+
1. *Positive Index:* Works the same as square bracket notation [].
9570+
2. *Negative Index:* Counts from the end of the array (e.g., -1 is the last element).
95669571

9567-
**Example:**
9572+
**Example:**
95689573

9569-
```javascript
9570-
const colors = ["Red", "Green", "Blue"];
9571-
// Old way to get the last element
9572-
console.log(colors[colors.length - 1]); // "Blue"
9574+
```javascript
9575+
const colors = ["Red", "Green", "Blue"];
95739576
9574-
// Using at()
9575-
console.log(colors.at(-1)); // "Blue"
9576-
console.log(colors.at(-2)); // "Green"
9577+
// Old way to get the last element
9578+
console.log(colors[colors.length - 1]); // "Blue"
95779579
9578-
// It also works on Strings
9579-
const sentence = "Hello";
9580-
console.log(sentence.at(-1)); // "o"
9580+
// Using at()
9581+
console.log(colors.at(-1)); // "Blue"
9582+
console.log(colors.at(-2)); // "Green"
95819583
9582-
// Comparing with bracket notation for negative index
9583-
console.log(colors[-1]); // undefined (Bracket notation looks for a property named "-1")
9584-
9584+
// It also works on Strings
9585+
const sentence = "Hello";
9586+
console.log(sentence.at(-1)); // "o"
95859587
9586-
**[⬆ Back to Top](#table-of-contents)**
9588+
// Comparing with bracket notation for negative index
9589+
console.log(colors[-1]); // undefined (Bracket notation looks for property "-1")
95879590
95889591
<!-- QUESTIONS_END -->
95899592
### Coding Exercise
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
Deep-Merge Two Nested Objects (with Circular References)
2+
Challenge:
3+
Implement a deep-merge function that combines two nested JavaScript objects while safely handling circular references. The function must be immutable and able to merge objects, arrays, and nested structures.
4+
5+
Problem Description:
6+
Deep merging means recursively combining the properties of two objects. When both inputs contain nested objects, arrays, or shared references, this becomes more complex.
7+
8+
Your task is to:
9+
Merge all properties from both objects
10+
Recursively merge nested objects
11+
Merge arrays by index
12+
Avoid infinite recursion when circular references exist
13+
Return a new, immutable object
14+
Ensure values from the second object override the first when conflicts occur
15+
Real-World Use Case
16+
State management libraries (Redux, Zustand, Immer)
17+
Complex configuration merging
18+
Deep cloning with overrides
19+
Normalizing API responses
20+
Merging schema definitions
21+
22+
Example:
23+
Input
24+
const a = {
25+
x: 1,
26+
y: { z: 2 }
27+
};
28+
a.self = a; // circular reference
29+
30+
const b = {
31+
y: { k: 20 },
32+
m: 100
33+
};
34+
b.loop = b; // circular reference
35+
36+
const result = deepMerge(a, b);
37+
38+
Output
39+
{
40+
x: 1,
41+
y: { z: 2, k: 20 },
42+
m: 100,
43+
self: [circular],
44+
loop: [circular]
45+
}
46+
47+
Requirements:
48+
Must deep-merge nested objects and arrays
49+
Must detect and safely handle circular references
50+
Must not mutate inputs
51+
When both objects contain the same key:
52+
If both values are objects → recursively merge
53+
If both are arrays → merge by index
54+
Otherwise → value from second object overrides
55+
Must create a brand-new object as the output
56+
57+
Key Concepts:
58+
Recursion
59+
WeakMap to track visited nodes
60+
Object and array cloning
61+
Circular reference detection
62+
Immutability principles
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Exercise: Deep-Merge Two Nested Objects (with Circular References)
2+
3+
## Problem Statement
4+
5+
Write a function **`deepMerge(objA, objB)`** that deeply merges two JavaScript objects **without mutating** either of them.
6+
The function must correctly merge nested structures and safely handle circular references.
7+
8+
---
9+
10+
## Rules
11+
12+
1. If a key exists only in one object → copy that value.
13+
2. If a key exists in both objects:
14+
- If both values are **plain objects**, recursively merge them.
15+
- If both values are **arrays**, merge by index (element-wise).
16+
- Otherwise, the value from **`objB`** overrides the value from **`objA`**.
17+
3. Handle **circular references** using a tracking mechanism like **WeakMap**.
18+
4. Always return a **new**, immutable object.
19+
5. Must preserve structure even when circular references appear on both inputs.
20+
21+
---
22+
23+
## Example
24+
25+
```js
26+
const a = {
27+
x: { y: 1 },
28+
arr: [1, 2]
29+
};
30+
a.self = a; // circular
31+
32+
const b = {
33+
x: { z: 2 },
34+
arr: [3],
35+
extra: true
36+
};
37+
b.loop = b; // circular
38+
39+
const result = deepMerge(a, b);
40+
41+
/*
42+
Expected structure:
43+
44+
{
45+
x: { y: 1, z: 2 },
46+
arr: [1, 3], // merged by index
47+
extra: true,
48+
self: <circular>,
49+
loop: <circular>
50+
}
51+
*/
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Deeply merges two objects while safely handling circular references.
3+
* Returns a new object without mutating the originals.
4+
*
5+
* @param {Object|Array} obj1
6+
* @param {Object|Array} obj2
7+
* @returns {Object|Array}
8+
*/
9+
function deepMerge(obj1, obj2, visited = new WeakMap()) {
10+
// If obj2 is primitive, return it directly
11+
if (obj2 === null || typeof obj2 !== "object") {
12+
return obj2;
13+
}
14+
15+
// Detect circular reference
16+
if (visited.has(obj2)) {
17+
return visited.get(obj2);
18+
}
19+
20+
// Determine output type
21+
const output = Array.isArray(obj1) ? [...obj1] :
22+
Array.isArray(obj2) ? [...obj2] :
23+
{ ...obj1 };
24+
25+
visited.set(obj2, output);
26+
27+
for (const key in obj2) {
28+
if (!obj2.hasOwnProperty(key)) continue;
29+
30+
const val1 = obj1 ? obj1[key] : undefined;
31+
const val2 = obj2[key];
32+
33+
if (val1 !== undefined && typeof val1 === "object" && typeof val2 === "object") {
34+
output[key] = deepMerge(val1, val2, visited);
35+
} else {
36+
output[key] = val2;
37+
}
38+
}
39+
40+
return output;
41+
}
42+
43+
// Example usage
44+
const a = { x: 1, y: { z: 2 } };
45+
a.self = a;
46+
47+
const b = { y: { k: 20 }, m: 100 };
48+
b.loop = b;
49+
50+
console.log(deepMerge(a, b));

0 commit comments

Comments
 (0)