深度复制具有属性的Javascript数组

时间:2016-12-29 08:52:00

标签: javascript arrays

使用.slice(),我可以深层复制原始类型的Javascript数组,例如:

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]

但是,如果我向arr添加属性,那么:

arr.prop1 = 5;

并做同样的事情:

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]

属性值不会延续到newArr

我考虑过不使用.slice()并循环使用arr的属性值,而是将它们分配给newArr,使用:

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]

这是使用属性深度复制这些数组的最快方法吗?我可以使用.slice()或其他数组方法以更简单或更清晰的方式执行此操作吗?我正在做这个操作数万次,并希望它尽可能干净和高效

2 个答案:

答案 0 :(得分:2)

如何使用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

答案 1 :(得分:2)

您正在尝试混合数组和对象(使数组的行为类似于对象) JavaScript 数组具有数字索引项目 JavaScript 对象具有字符串索引项。

数组具有 length 属性,该属性可以告知数组中有多少项,并在向数组中添加或删除项时自动更新。
但是......

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

console.log(arr.length);

输出为4,但您希望它为5
arr.prop1 = 7实际上并未添加到数组中。
设置字符串参数添加到底层对象 仅当您向数组添加项而不是基础对象时,才会修改 length 属性。
表达式newArr = arr.slice()将新数组分配给newArr,因此它仍然是一个数组,其行为类似于数组。

  

属性值不会转移到newArr

如果您仍想继续使用混合数字/字符串索引序列,克隆它们,请尝试使用Object.assign()函数。对于你的情况,这应该是最简单的方法:

  

Object.assign()方法用于复制all的值   枚举从一个或多个源对象到目标的自有属性   对象

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

输出:

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

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