简体   繁体   中英

Deep copy Javascript array with properties

Using .slice() , I can deep copy a Javascript Array of primitive types, for example:

var arr = [1,2,3,4];
var newArr = arr.slice();
newArr.push(5);
console.log(arr); // [1,2,3,4]
console.log(newArr); // [1,2,3,4,5]

However, If I add a property to arr like so:

arr.prop1 = 5;

and do the same:

var arr = [1,2,3,4];
arr.prop1 = 8;
arr.prop2 = 9;
var newArr = arr.slice();
newArr.push(5);
console.log(arr); // [1, 2, 3, 4, prop1: 9, prop2: 8]
console.log(newArr); //  [1, 2, 3, 4, 5]

The property values do not carry over to newArr

I have considered not using .slice() and looping over the property values of arr instead, assigning them to newArr , using :

for (var key in arr) {
  if (arr.hasOwnProperty(key)) {
    newArr[key] = arr[key];
  }
}
console.log(arr); // [1, 2, 3, 4, prop1: 9, prop2: 8]
console.log(newArr); //  [1, 2, 3, 4, 5, prop1: 9, prop2: 8]

Is this going to be the quickest way to deep copy these arrays with properties? Is there in easier or cleaner way I can do this using .slice() or another array method? I am doing this operation tens of thousands of times and want it to be as clean and efficient as possible

How about using Object.create(proto)

var arr = [1,2,3,4];
arr.prop1 = 8;
arr.prop2 = 9;
var newArr = Object.create(arr);

newArr.prop1 = 12;
console.log(arr.prop1) // 8
console.log(newArr.prop1) // 12

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

You are trying to mix an array and object(to make an array behave like an object).
JavaScript array has numeric indexed items.
JavaScript object has string indexed items.

Arrays have a length property that tells how many items are in the array and is automatically updated when you add or remove items to the array.
But ...

var arr = [1,2,3,4], newArr = arr.slice();
arr.prop1 = 7;

console.log(arr.length);

The output is 4 , though you would expect it to be 5 .
But arr.prop1 = 7 does not actually add to the array.
Setting a string parameter adds to the underlying object .
The length property is only modified when you add an item to the array, not the underlying object.
The expression newArr = arr.slice() assigns a new array to newArr , so it remains an array and behaves like a pure array.

The property values do not carry over to newArr

If you still want to proceed using mixed numeric/string indexed sequences, cloning them, try using Object.assign() function. This should be the easiest way for your case:

The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

console.log(Object.assign(newArr, arr));

The output:

[1, 2, 3, 4, prop1: 7]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM