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:
-
Countdown Timer in JavaScript
Often on sites that sell something, you can find a countdown timer to a certain date. Such a script is usually needed for landing pages or online stores. In one of the pr...
-
Drop down menu (jQuery)
Drop down menu can be done without JavaScript, only with the help of CSS. With :hover. But the JavaScript menu has its advantages. The most important thing is the delay i...
-
jQuery Accordion Plugin
An accordion is often used on websites. This element is popular and convenient at the same time. An accordion helps to structure content and save space. In my work, I oft...
Leave a Reply