When trying to copy an array for the first time many new developers might just try to assign an array value from one variable to another. The expectation might be that arrays can be copied in the same way as one might have grown accustomed to when it comes to primitive values like numbers and strings. However when trying to copy an array like this all that is happening is that the developer is creating a new reference to the same array, and not copying, or cloning if you prefer, a new array.
So then a salutation to this would be finding a way to preform what is often called a shallow clone, or a deep clone in the event of an array of arrays, or any amount of nested objects that would also need to be copied. For starters lets look at at some ways to create a shallow clone that will work fine when it comes to a simple array of primitive values such as in this above example.
Just get it done any way possible and move on right? Sure thing with that said one way to go about copying an array is to just create a new array, and just loop over the contents of the source array and add each of the source array elements into the new array. One way of doing it would be to start off by just create a new array with the Array constructor, or the array literal bracket syntax. Then loop over the source array, such as with a while loop, or the array for each method, and set each index in the new array to the corresponding index value in the source array that is to be copied.
This crude yet effective way of copying an array will work just fine with arrays with primitive values, but it will just be the same problem when it comes to nested arrays. However maybe it would still be a good idea to look into some additional options for marking a shallow copy of an array, before moving on to that sort of thing.
One way to create a shallow clone or copy of an array would be to use the array slice method. The array slice method should not be confused with the array spice method which will mutate a source array in place. unlike the array splice method the array slice method will return a new array, with elements between a starting and ending index that are given as arguments when calling array slice. I could give the value of zero for the first argument to array slice, and the length of the array as the second argument, or better yet no arguments at all as the default with no arguments will be a shallow clone of the array, that is a new array with all the values from the original source array.
In some cases I see people recommending the Array.from method as a way to make a copy of an array. This will work okay as yet another option for just making shallow copies of an array. That is it will work with an array of numbers, strings, booleans and so forth. However once again this will fall short when it comes to making a deep copy when it comes to nested objects as elements in the array that is to be copied.
The Object.assign method will come up a lot in discussions, it to is anther option for making a shallow clone of an array. The name should give it away, assign, it is just like using the assignment operator with things. The thing about it though is that I can give not just one source array, but start off with a new array as the first argument, then the source array. This will result in the values of the source array being, you guessed it assigned to the new array that I passed as the first argument. So then the end result is yet another shallow clone, at least when used by itself this way.
I covered this before hand in the previous section when it comes to using a method like slice. The problem with using the array slice method, or any shallow clone method with an array of objects is that doing so will create a new array rather than just a reference to the same array, but it will not do anything with additional references that are elements of the array.
So if I have an array of objects rather than just a simple array of numbers, and I use something like array slice to copy the array. It will create a new array, but it will still be the same references to the same objects when it comes to the arrays contents.
This is where it becomes necessary to do something that can be called deep cloning of an object or array. In these situations I often do not just want to copy the array itself, but also make copies of any and all nested objects in the array that are part of the arrays contents. It might be possible to create such a solution using array slice, just not by itself.
If I am dealing with an array of objects, and each array is just a shallow object that does not have any additional nested objects in each element, then it would not be to hard to just use something like the array map method. I could call the map method off of the source array, and then return a new object in the body of the method that I pass to array map. Like the array slice method the array map will return a new array rather than mutating an array in place. On top of that I can returned whole new objects when it comes to defining the product that is return for each element in the source array. So depending on how I use the array map method this ca be used as a quick way to deep clone something.
The result is not just a new array, but new objects for each element also, not just references.
Another crude yet effective deep clone trick is to use JSON.stringify to convert a whole object such as an array as well as all nested objects into a JSON string. Then I can just use the JSON.parse method to parse that string back into a workable object. In most cases this will work when dealing with plain old objects like this, and it will even work as a deep clone method for many levels of nested objects also.
To start off with I quickly put together a method that can be used to traverse public keys of an object. There are a number of ways to go about making this kind of method, but they will typically include using something like a for in loop, and calling the method itself in the body of the method for object properties that are a nested object. When calling this kind of method I will want to give the object to traverse, along with a method that will be called for each key and value pair that will be found. In the body of this for key method I can have access to all the usual arguments of interest fr a given key value pair in an object, such as the value, the key, the type, and it would also be nice to know the level from the root object also.
So then now that I have a traverse method to work with I can now use this method to address all kinds of weird situations in which i may need to assign and deep clone as needed.