How can I copy every element of an array (where the elements are objects), into another array, so that they are totally independent? I don't want changing an element in one array to affect the other.
If the destination array doesn't exist yet...
...you can use slice() or concat(). slice() is probably more idiomatic (you'll also see slice(0), but the default is 0, so...):
var destinationArray = sourceArray.slice(); // Probably more idiomatic
// or
var destinationArray = sourceArray.concat();
As of ES2015 (aka ES6), there's also Array.from, which creates a new array from any array-like thing (including an actual array):
var destinationArray = Array.from(sourceArray);
(Array.from can be shimmed/polyfilled for older JavaScript engines.)
Also as of ES2015, you can use iterable spread notation and an array literal with any iterable (including an array):
var destinationArray = [...sourceArray];
After that, both arrays will have the same contents. Changing one array will not change the other. Naturally, if an array entry is an object, the entry for that object in both arrays will point to the same object; this isn't a "deep" copy.
If the destination array exists...
...and you want to append the contents of the source array to it, you can use push:
destinationArray.push.apply(destinationArray, sourceArray);
That works by calling push on the destination array using the apply feature of JavaScript functions, which lets you specify the arguments for the function call as an array. push will push as many elements as it has arguments, so it ends up copying the elements from the source array to the destination array.
In ES2015 and later, you can make that cleaner with iterable spread notation (...):
destinationArray.push(...sourceArray);
Note that in both cases, the call is limited by the JavaScript engine's maximum number of function arguments (as of this writing, that's at least in the thousands for all major engines [and not in the hundreds of thousands, at least not for Chrome's V8]).
Here's an ES5 version:
var source1, dest1, source2, dest2;
snippet.log("If dest doesn't exist yet:");
source1 = [1, 2, 3, 4];
dest1 = source1.slice(0);
snippet.log("[before change] source1 = " + source1.join(", "));
snippet.log("[before change] dest1 = " + dest1.join(", "));
source1[2] = "three";
dest1[3] = "four";
snippet.log("[after change] source1 = " + source1.join(", "));
snippet.log("[after change] dest1 = " + dest1.join(", "));
snippet.log("If dest already exists and we're just appending:");
source2 = [1, 2, 3, 4];
dest2 = ['a', 'b', 'c', 'd'];
snippet.log("[before append] source2 = " + source2.join(", "));
snippet.log("[before append] dest2 = " + dest2.join(", "));
dest2.push.apply(dest2, source2);
snippet.log("[before change] source2 = " + source2.join(", "));
snippet.log("[before change] dest2 = " + dest2.join(", "));
source2[2] = "three";
dest2[7] = "four";
snippet.log("[after change] source2 = " + source2.join(", "));
snippet.log("[after change] dest2 = " + dest2.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Easy way to get this working is using:
var cloneArray = JSON.parse(JSON.stringify(originalArray));
I have issues with getting arr.concat() or arr.splice(0) to give a deep copy. Above snippet works perfectly.
A great way for cloning an array is with an array literal and the spread operator. This is made possible by ES2015.
let objArray = [{name:'first'}, {name:'second'}, {name:'third'}, {name:'fourth'}];
let clonedArr = [...objArray];
console.log(clonedArr) // [Object, Object, Object, Object]
You can find this copy option in MDN's documentation for spread operators https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array
It is also an Airbnb's best practice. https://github.com/airbnb/javascript#es6-array-spreads
Note: Typically the spread operators in ES2015 goes one level deep while copying an array. Therefore, they are unsuitable for copying multidimensional arrays.
var clonedArray = array.concat();
If you want to keep reference:
Array.prototype.push.apply(destinationArray, sourceArray);
There are two important notes.
- Using
array.concat()does not work using Angular 1.4.4 and jQuery 3.2.1 (this is my environment). - The
array.slice(0)is an object. So if you do something likenewArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0), the two new arrays will reference to just 1 array and changing one will affect the other.
Alternatively, using newArray1 = JSON.parse(JSON.stringify(old array)) will only copy the value, thus it creates a new array each time.
I suggest using concat() if you are using nodeJS. In all other cases, I have found that slice(0) works fine.
来源:https://stackoverflow.com/questions/16232915/copying-an-array-of-objects-into-another-array-in-javascript