How to Implement and Use Deep Copy and Shallow Copy in JavaScript
Copying objects and arrays is a fundamental task in JavaScript development. This article breaks down the concepts of deep copy and shallow copy, explains their implementation methods, and discusses their advantages, disadvantages, and practical applications.
Deep Copy vs. Shallow Copy
-
Deep Copy: Creates an entirely new object, recursively duplicating all nested objects. Changes to the copied object do not affect the original.
-
Shallow Copy: Copies only the top-level properties. Nested objects remain references to the original, meaning changes to them reflect in both objects.
Methods to Implement Deep Copy
Using JSON.stringify
and JSON.parse
1 function deepClone(obj) {2 return JSON.parse(JSON.stringify(obj));3 }
- Pros: Simple and effective for basic data structures.
- Cons: Fails with special objects like
Date
,RegExp
, or circular references.
Manual Recursion
1 function deepClone(obj) {2 if (typeof obj !== 'object' || obj === null) return obj;3 const clone = Array.isArray(obj) ? [] : {};4 for (let key in obj) {5 if (obj.hasOwnProperty(key)) clone[key] = deepClone(obj[key]);6 }7 return clone;8 }
- Pros: Handles custom object types and circular references with additional logic.
- Cons: More complex to implement.
Using structuredClone
1 const clonedObj = structuredClone(originalObj);
- Pros: Native support in modern browsers for deep copying complex types.
- Cons: Not available in older browsers.
Third-Party Libraries (e.g., Lodash)
1 import cloneDeep from 'lodash/cloneDeep';2 const clonedObj = cloneDeep(originalObj);
- Pros: Optimized for edge cases, supports circular references.
- Cons: Adds project dependencies.
Methods to Implement Shallow Copy
slice()
or concat()
1 const shallowCopy = originalArray.slice();2 const shallowCopy2 = originalArray.concat();
Spread Operator (...
)
1 const shallowCopy = [...originalArray];
Array.from()
1 const shallowCopy = Array.from(originalArray);
Key Note: Changes to nested objects in a shallow copy affect the original.
Key Considerations
- Circular References: Deep copy methods like recursion or libraries handle circular references better than
JSON.stringify
. - Performance: Deep copying large or complex objects can be resource-intensive.
- Special Objects: Special types (e.g.,
Date
,RegExp
) require customized handling for accurate copying.
By understanding these methods, you can choose the best copy technique for your needs, balancing performance, compatibility, and complexity.