It is important to understand how to clone arrays in JavaScript to manage data more effectively. In this article, we will learn how to do deep cloning in JavaScript. There are many types of deep cloning, and we have covered them all. So let's enhance your skills in JavaScript.
Let's begin!
Table of contents
- JavaScript Array Cloning Techniques
- Deep Clone Array JavaScript
- JSON vs Lodash Array Cloning
- Best Practices for Deep Cloning Arrays
1. JavaScript Array Cloning Techniques
Arrays in JavaScript are fundamental data structures used to store collections of elements. When you need to duplicate an array, ensure that modifications made to one array don't affect the original. At that time, array cloning techniques come into play.
There are primarily two types of copying arrays or objects: shallow copy and deep copy. A shallow copy of an array only makes a copy of the outermost layer, leaving the inner arrays linked to the original. Not understood? Don't worry, see the example for easy understanding.
let originalArray = [1, 2, [3], 4];
let copiedArray = [...originalArray]; // create copy with shallow copy
// Change the element of the array(outermost layer) and in the nested array
copiedArray[0] = 10;
copiedArray[2][0] = 20;
// Original array affected
console.log(originalArray); // [ 1, 2, [ 20 ], 4 ]
console.log(copiedArray); // [ 10, 2, [ 20 ], 4 ]
In this example, we have an array originalArray consisting of elements [1, 2, [3], 4]. Using the spread operator, we create a shallow copy named copiedArray. When we modify copiedArray[0] to 10, it doesn't affect originalArray as it only changes the top-level element.
But, when modifying the nested array, like copiedArray[2][0] to 20, it will impact both the originalArray and the copiedArray. This is because copiedArray is a shallow copy, which duplicates only the top level of the array without altering the original. Consequently, changes made to nested elements are reflected in both arrays. As a result, console.log(originalArray) outputs [1, 2, [20], 4], while console.log(copiedArray) outputs [10, 2, [20], 4].
If we use Object.assign() or the spread operator (...) to copy an array, it means we are using shallow copy. So, if the array contains nested or multi-dimensional elements, modifying the copied array will also affect the original array.
If you want a completely independent copy of all nested arrays, you need to use a deep clone. Let's see how we can use deep copy for copying arrays.
2. Deep Clone Array JavaScript
There are many ways to perform deep cloning in JavaScript, but I will teach you 3 ways with the code example that are most used and also easy.
- Using JSON methods
- Using a library like Lodash:
- Using custom recursive function:
let originalArray = [1, 2, [3], 4];
// Create a copy with a deep copy
let arrayCopy = JSON.parse(JSON.stringify(originalArray));
// Change element of the array and in the nested array
copiedArray[0] = 10;
copiedArray[2][0] = 20;
// Original not affected
console.log(originalArray); // [ 1, 2, [ 3 ], 4 ]
console.log(copiedArray); // [ 10, 2, [ 20 ], 4 ]
In this code snippet, we have an array originalArray containing elements [1, 2, [3], 4]. To create a deep copy of this array, we use the JSON.parse(JSON.stringify(originalArray)) method, resulting in copiedArray.
When we modify copiedArray[0] to 10 and copiedArray[2][0] to 20, it does not affect the original originalArray. This is because copiedArray is a deep copy, meaning it replicates the entire structure of the array, including nested arrays, without referencing the original. As a result, console.log(originalArray) outputs [1, 2, [3], 4], while console.log(copiedArray) outputs [10, 2, [20], 4].
Now you should understand how deep copy works and what the difference is between shallow and deep copy. Now, we can take a different approach to get the same result. The output is the same, but we have an additional choice.
Example: (using a library like Lodash)
const _ = require('lodash');
const originalArray = [1, [2], [3, [4]], 5];
const copiedArrayWithLodas = _.cloneDeep(originalArray);
copiedArrayWithLodas[1][0] = 10;
copiedArrayWithLodas[2][1][0] = 8;
console.log(originalArray); // [ 1, [ 2 ], [3, [4] ], 5 ]
console.log(copiedArrayWithLodas); // [ 1, [ 10 ], [3, [8] ], 5 ]
function deepCloneArray(arr) {
return arr.map(item => Array.isArray(item) ? deepCloneArray(item) : item);
}
const originalArray = [1, [2], [3, [4]], 5];
const copiedArrayRecursiveFunc = deepCloneArray(originalArray);
copiedArrayRecursiveFunc[0] = 10
copiedArrayRecursiveFunc[1][0] = 20
console.log(originalArray); // [ 1, [ 2 ], [ 3, [ 4 ] ], 5 ]
console.log(copiedArrayRecursiveFunc); // [ 10, [ 20 ], [ 3, [ 4 ] ], 5 ]
This code copies arrays using a function called deepCloneArray. First, it makes a copy of an array called originalArray and stores it in copiedArrayRecursiveFunc using deepCloneArray. Then, it changes the first item in copiedArrayRecursiveFunc to 10 and the first item in its nested array to 20. After that, it shows both arrays. The originalArray stays the same, but copiedArrayRecursiveFunc shows the changes made.
4. JSON vs Lodash Array Cloning
When you're deciding whether to use JSON or Lodash to copy arrays, think about what your project needs. Here are some helpful suggestions to guide you in making the right choice.
JSON Array Cloning:
- Optimal for simplicity if you require basic, shallow copying.
- Best for scenarios where you want to avoid external dependencies.
- However, it's limited to shallow copying and may not handle complex arrays well.
Lodash Array Cloning:
- Choose Lodash for more advanced array manipulation needs.
- Ideal for deep cloning or managing non-serializable values.
- Offers a comprehensive set of tools for array operations.
- Keep in mind that it adds a dependency to your project and may increase bundle size.
5. Best Practices for Deep Cloning Arrays
Using Lodash's cloneDeep() function: Utilize dedicated tools like Lodash's cloneDeep() function, designed specifically for deep cloning arrays. These libraries offer robust solutions with well-tested implementations.
Implementing custom recursive functions: If you prefer not to use external libraries, you can create your own recursive function to deep-clone arrays. Ensure the function properly handles nested arrays and objects.
Avoiding JSON methods for deep cloning: While JSON.parse(JSON.stringify(array)) can be used for shallow cloning, it is not suitable for deep cloning as it does not preserve non-serializable values like functions or symbols.
Thorough testing: Extensive testing across various scenarios helps verify the correctness and robustness of your deep cloning implementation, ensuring it handles edge cases effectively.
Document comprehensively: Documenting your deep cloning process within your codebase enhances readability and facilitates maintenance, ensuring other developers can understand and modify the code as needed.
Conclusion
It is important to understand deep cloning for data manipulation. We have told you three ways to use deep cloning, which you can use according to your project. Make sure to practice what we've covered; it'll help you get a better grasp of the idea.