Skip to content

Commit e854278

Browse files
Add guide and examples for shallow vs deep copy in JS
Introduced a markdown guide explaining the differences between shallow and deep copy in JavaScript, including definitions, methods, and visual diagrams. Added a JavaScript file with practical code examples demonstrating shallow and deep copy techniques, their effects, and a custom deep copy function.
1 parent 946822a commit e854278

File tree

3 files changed

+254
-0
lines changed

3 files changed

+254
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Shallow Copy vs Deep Copy in JavaScript
2+
3+
Understanding how JavaScript handles data updating is crucial when working with objects and arrays. This guide explains the differences between Shallow Copy and Deep Copy.
4+
5+
## Primitive vs Reference Types
6+
7+
Before diving into copying, it's important to remember:
8+
* **Primitive types** (string, number, boolean, etc.) are passed by **value**.
9+
* **Reference types** (objects, arrays) are passed by **reference**.
10+
11+
## Shallow Copy
12+
13+
A **shallow copy** creates a new object, but it does not create copies of nested objects. Instead, it copies the *references* to those nested objects.
14+
15+
NOTE : A shallow copy duplicates the outer container while preserving references to all nested objects, causing shared mutable state across copies.
16+
17+
### Definition
18+
* Top-level properties are copied by value (if primitive).
19+
* Nested objects/arrays are copied by reference.
20+
* **Consequence**: Modifying a nested object in the copy **changes the original**.
21+
22+
### How to create a Shallow Copy
23+
1. `Object.assign()`
24+
2. Spread Operator `[...]` or `{...}`
25+
26+
### Example
27+
28+
```javascript
29+
let original = {
30+
name: "Aditya",
31+
social: {
32+
twitter: "@aditya"
33+
}
34+
};
35+
36+
let shallowCopy = { ...original };
37+
38+
shallowCopy.name = "Ashok"; // Does NOT affect original (Top-level primitive)
39+
shallowCopy.social.twitter = "@newHandle"; // AFFECTS original (Nested reference)
40+
41+
console.log(original.name); // "Aditya"
42+
console.log(original.social.twitter); // "@newHandle" - CHANGED!
43+
```
44+
45+
### Visual Representation
46+
47+
```mermaid
48+
graph LR
49+
subgraph Memory
50+
Obj1[Object: {name: "Aditya"}]
51+
Obj2[Object: {name: "Ashok"}]
52+
Nested[Shared Nested Object: {twitter: "@newHandle"}]
53+
end
54+
55+
Original[Original Var] --> Obj1
56+
Copy[Shallow Copy Var] --> Obj2
57+
58+
Obj1 -- reference --> Nested
59+
Obj2 -- reference --> Nested
60+
61+
style Nested fill:#f9f,stroke:#333
62+
```
63+
64+
> [!WARNING]
65+
> Use shallow copies only when your object structure is flat (no nested objects) or when you specifically want shared state for nested items.
66+
67+
---
68+
69+
## Deep Copy
70+
71+
A **deep copy** creates a completely independent clone of the original object, including all nested objects.
72+
NOTE : Deep copy recreates the entire object graph with no shared references, requiring recursive traversal and new allocations for every nested structure.
73+
74+
### Definition
75+
* recursively copies all properties.
76+
* New memory references are created for every nested object.
77+
* **Consequence**: Modifying the copy **never affects the original**.
78+
79+
### How to create a Deep Copy
80+
1. `JSON.parse(JSON.stringify(obj))` (Simple, but has limitations: no functions, symbols, or undefined).
81+
2. `structuredClone(obj)` (Modern standard).
82+
3. Lodash `_.cloneDeep(obj)` (External library).
83+
4. Recursive custom function.
84+
85+
### Example
86+
87+
```javascript
88+
let original = {
89+
name: "Aditya",
90+
social: {
91+
twitter: "@aditya"
92+
}
93+
};
94+
95+
let deepCopy = JSON.parse(JSON.stringify(original));
96+
97+
deepCopy.social.twitter = "@deepNew";
98+
99+
console.log(original.social.twitter); // "@aditya" - Unchanged!
100+
console.log(deepCopy.social.twitter); // "@deepNew"
101+
```
102+
103+
### Visual Representation
104+
105+
```mermaid
106+
graph LR
107+
subgraph Memory
108+
Obj1[Original Object]
109+
Nested1[Nested Object 1]
110+
111+
Obj2[Deep Copied Object]
112+
Nested2[Nested Object 2]
113+
end
114+
115+
Original[Original Var] --> Obj1
116+
Obj1 -- reference --> Nested1
117+
118+
Copy[Deep Copy Var] --> Obj2
119+
Obj2 -- reference --> Nested2
120+
121+
style Obj1 fill:#bef,stroke:#333
122+
style Obj2 fill:#bef,stroke:#333
123+
style Nested1 fill:#bfb,stroke:#333
124+
style Nested2 fill:#bfb,stroke:#333
125+
```
126+
127+
### Comparison Summary
128+
129+
| Feature | Shallow Copy | Deep Copy |
130+
| :--- | :--- | :--- |
131+
| **Top-level properties** | Copied | Copied |
132+
| **Nested Objects** | Shared Reference | Independent Copy |
133+
| **Memory Usage** | Low | High |
134+
| **Speed** | Fast | Slow |
135+
| **Methods** | `Object.assign`, spread | `JSON.parse/stringify`, `structuredClone` |
136+
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
let a = {
2+
name: "Aditya",
3+
age: 25,
4+
};
5+
6+
let b = a;
7+
b.name = "Ashok";
8+
// console.log(a);
9+
// console.log(b);
10+
let c = {
11+
name: "Sweta",
12+
age: 25,
13+
};
14+
let d = Object.assign(c);
15+
16+
d.name = "mamta";
17+
18+
// console.log(c);
19+
// console.log(d);
20+
21+
let profile = {
22+
name: "Aditya",
23+
age: 25,
24+
gender: "male",
25+
social: {
26+
facebook : 'cooldude',
27+
twitter : 'aditya',
28+
followersCount : {
29+
fb_count : 100,
30+
twitter_count : 200
31+
}
32+
33+
}
34+
};
35+
36+
let newProfile = {...profile}; // using spread operator , it Creates a Shallow copy - only the top level structure
37+
// when we use spread operator it only copies the first level properties, and nested objects are still referenced.
38+
39+
newProfile.age = 30
40+
console.log(profile);
41+
console.log(newProfile)
42+
43+
newProfile.social.facebook = 'changedDude';
44+
newProfile.social.followersCount.fb_count = 2000000;
45+
46+
console.log(profile.social.facebook)
47+
48+
console.log(newProfile.social.facebook);
49+
50+
51+
console.log(profile.social.followersCount.fb_count); //2000000 because both are referring to same object in memory
52+
53+
54+
console.log(newProfile.social.followersCount.fb_count); //2000000 because both are referring to same object in memory
55+
56+
/*
57+
* A shallow copy duplicates only the top-level structure of a data object.
58+
* All nested objects, arrays, functions, and reference types are not duplicated.
59+
* Instead, their memory references are copied.
60+
61+
62+
* A shallow copy duplicates the outer container while preserving references to all nested objects, causing shared mutable state across copies.
63+
*/
64+
65+
// Deep Copy
66+
let deepCopiedProfile = JSON.parse(JSON.stringify(profile)); // Creates a Deep copy but it has limitations - only works with JSON serializable data types
67+
/*
68+
* JSON.stringify() converts the object into a JSON string, effectively breaking all references to nested objects.
69+
* JSON.parse() then takes that string and constructs a new object from it, resulting in a completely independent copy of the original object.
70+
*/
71+
72+
deepCopiedProfile.age = 35;
73+
deepCopiedProfile.social.twitter = 'newTwitterHandle';
74+
deepCopiedProfile.social.followersCount.twitter_count = 500000;
75+
76+
console.log(deepCopiedProfile.social.followersCount.twitter_count); //500000 - deep copy has its own copy
77+
console.log(profile.social.twitter); // 'aditya' - original remains unchanged
78+
console.log(deepCopiedProfile.social.twitter); // 'newTwitterHandle' - deep copy has its own copy
79+
80+
81+
function deepCopy(value) {
82+
if (value === null || typeof value !== "object") {
83+
return value;
84+
}
85+
86+
const result = Array.isArray(value) ? [] : {};
87+
88+
for (const key in value) {
89+
if (Object.hasOwn(value, key)) {
90+
result[key] = deepCopy(value[key]);
91+
}
92+
}
93+
94+
return result;
95+
}
96+
97+
98+
console.log('deep copy:', deepCopy(profile));
99+
100+
/*
101+
* Deep copy recreates the entire object graph with no shared references, requiring recursive traversal and new allocations for every nested structure.
102+
103+
104+
* A deep copy duplicates not only the top-level structure of a data object but also all nested objects, arrays, functions, and reference types.
105+
* Each level of the data structure is recursively copied, resulting in a completely independent clone of the original object.
106+
107+
108+
* typeof returns strings
109+
110+
* Valid outputs:
111+
* "object", "function", "string", "number", "boolean", "undefined", "symbol", "bigint"
112+
113+
*/
114+
115+
/*
116+
* A deep copy creates entirely independent objects at all levels of the data structure, ensuring no shared references between the original and the copy.
117+
*/

index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- [loops](loops/loops.md)
66
- [String](string/string.md)
77
- [Arrays](Arrays/array.md)
8+
- [Deep Copy vs Shallow Copy](DeepCopyVSShallowCopy/shallow-deep-copy.md)
89
- [Sets](map-set/set.md)
910
- [JavaScript Regular Expression](string/regex.md)
1011
- [Functions](functions/functions.md)

0 commit comments

Comments
 (0)