Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 783
Gerard Simpson Avatar asked Aug 09 '26 04:08

Gerard Simpson


2 Answers

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

like image 89
RomanPerekhrest Avatar answered Aug 11 '26 16:08

RomanPerekhrest


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

like image 37
Shanimal Avatar answered Aug 11 '26 16:08

Shanimal