How to Сlone (Copy) Object and Array in JavaScript
Cloning an Array
1. Using the Spread Operator (...):
const originalArray = [1, 2, 3]; const clonedArray = [...originalArray]; console.log(clonedArray); // Output: [1, 2, 3]
2. Using Array.prototype.slice():
const originalArray = [1, 2, 3]; const clonedArray = originalArray.slice(); console.log(clonedArray); // Output: [1, 2, 3]
3. Using Array.from():
const originalArray = [1, 2, 3]; const clonedArray = Array.from(originalArray); console.log(clonedArray); // Output: [1, 2, 3]
4. Using structuredClone() (Deep Clone):
const originalArray = [1, { key: "value" }];
const clonedArray = structuredClone(originalArray);
console.log(clonedArray); // Output: [1, { key: "value" }]
Cloning an Object
1. Using the Spread Operator (...):
const originalObject = { a: 1, b: 2 };
const clonedObject = { ...originalObject };
console.log(clonedObject); // Output: { a: 1, b: 2 }
2. Using Object.assign():
const originalObject = { a: 1, b: 2 };
const clonedObject = Object.assign({}, originalObject);
console.log(clonedObject); // Output: { a: 1, b: 2 }
3. Using structuredClone() (Deep Clone):
const originalObject = { a: 1, b: { c: 2 } };
const clonedObject = structuredClone(originalObject);
console.log(clonedObject); // Output: { a: 1, b: { c: 2 } }
4. Using JSON.parse() and JSON.stringify() (Deep Clone):
const originalObject = { a: 1, b: { c: 2 } };
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject); // Output: { a: 1, b: { c: 2 } }
This method does not support functions, undefined, Symbol, or circular references.
Deep Cloning vs. Shallow Cloning
- Shallow Cloning (e.g., using
...,slice(), orObject.assign()):
Only clones the first level of the object or array. Nested objects or arrays remain references to the original. - Deep Cloning (e.g.,
structuredClone()orJSON.parse(JSON.stringify())):
Clones the entire structure, including nested objects or arrays.
When to Use Each Method
- Use shallow cloning for simple, flat structures.
- Use deep cloning if the object or array contains nested structures and you need to avoid references to the original data.
Сloning an Array or Object That Contains Methods (Functions)
Shallow Cloning
Using the Spread Operator (...) or Object.assign()
- Functions in the object or array are treated like any other property.
- The reference to the function is copied to the cloned object or array.
- The original and cloned versions will share the same function in memory.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = { ...originalObject };
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
For Arrays: If the array contains functions, the references to those functions are copied. Using the Spread Operator (...) or slice()
const originalArray = [1, 2, function () { return 42; }];
const clonedArray = [...originalArray];
console.log(clonedArray[2]()); // Output: 42
console.log(clonedArray[2] === originalArray[2]); // Output: true (same reference)
Deep Cloning
Using JSON.parse(JSON.stringify())
- Methods (functions) will be lost because JSON only supports serializable data types (e.g., numbers, strings, arrays, and objects).
- Any properties containing functions will not exist in the cloned object or array.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject.method); // Output: undefined
Using structuredClone() (Deep Clone)
Functions are not cloned. Structured cloning does not support functions and will remove them from the cloned object or array.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = structuredClone(originalObject);
console.log(clonedObject.method); // Output: undefined
Key Points to Remember
1. Shallow Cloning:
- Functions are copied by reference, meaning the cloned and original objects/arrays will share the same function.
2. Deep Cloning:
- Functions are usually lost (removed) when using methods like
JSON.parse(JSON.stringify())orstructuredClone()because they are not serializable.
3. If you need to clone an object or array with methods, you may need to write a custom clone function to handle the functions explicitly or use third-party libraries.
Custom Cloning for Objects with Methods
You can handle functions manually in your cloning logic:
function customClone(obj) {
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (typeof obj[key] === 'function') {
clone[key] = obj[key]; // Copy functions by reference
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
clone[key] = customClone(obj[key]); // Recursively clone objects
} else {
clone[key] = obj[key]; // Copy primitives
}
}
return clone;
}
const original = {
value: 42,
method() {
return this.value;
}
};
const cloned = customClone(original);
console.log(cloned.method()); // Output: 42
console.log(cloned.method === original.method); // Output: true (same reference)
This approach ensures functions are preserved while deeply cloning other properties.
Using Third-party Libraries
In projects I often use Lodash or jQuery. Both of these libraries have deep cloning methods. When using Lodash or jQuery to perform deep cloning, both libraries treat functions differently than native methods like JSON.parse(JSON.stringify()) or structuredClone().
Deep Cloning with Lodash
Using Lodash’s _.cloneDeep():
- Lodash performs a deep clone of the object or array, including nested structures.
- Functions (methods) in the object or array are copied by reference. This means that the function in the cloned object or array will point to the same memory reference as the original.
const _ = require('lodash');
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = _.cloneDeep(originalObject);
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Lodash does not remove functions, unlike JSON.parse(JSON.stringify()), but it doesn’t create a new copy of the function. It retains a reference to the original.
Deep Cloning with jQuery
Using jQuery’s $.extend():
- jQuery’s
$.extend()is used for cloning objects. To achieve a deep clone, you pass true as the first argument. - Like Lodash, jQuery copies functions by reference.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = $.extend(true, {}, originalObject);
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Limitations of $.extend():
- jQuery’s cloning mechanism is simpler and less robust compared to Lodash.
- It does not handle some advanced use cases (e.g., circular references) as efficiently as Lodash.
Similar posts:
-
Finding the Distance Between Two Points on a Map Using JavaScript (TypeScript)
If you have the coordinates of two points on a map, calculating the distance between them is a fairly straightforward task. This type of calculation is commonly used in m...
-
How to Make Asynchronous Requests in a Loop in JavaScript
Implementing asynchronous requests inside a JavaScript loop may not seem obvious at first. When making asynchronous requests inside a JavaScript loop, it is important to ...
-
How to Detect Scroll Direction on a Page Using JavaScript
Sometimes it is necessary to detect the direction of vertical scrolling on a site, for example, to perform some actions with the footer or header. Let's write code to det...
Leave a Reply