来自mdn:Spread Syntax
注意:通常,ES2015中的扩展运算符在复制数组时会变深一级。因此,它们不适合复制多维数组。与Object.assign()和Object spread语法的情况相同。请查看下面的示例以便更好地理解。
var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Now array b is: [[2], [3]]
以上陈述的重点是什么?上面的代码示例的工作方式与使用.slice()方法将数组复制到a中的方法相同。我尝试在这里向数组添加另一个维度:https://repl.it/HKOq/2并且事情仍按预期工作。
那么为什么扩展语法不适合复制多维数组呢?
我很感激任何帮助。
编辑:
阅读estus和vol7ron的答案帮助我解决问题。基本上,正如estus在技术上指出的那样,数组内部只有数组而不是多维数组。
正如vol7ron解释的那样,只复制了数组的第一级,因此内存中的对象对于任何其他嵌套元素保持不变。
我怀疑使用扩展语法与切片运算符的行为有什么不同我也错了
答案 0 :(得分:3)
数组是对象,[...a]
创建a
数组对象的浅副本。
对于语言本身,没有多维数组 - 数组中有另一个数组。包含数组,普通对象,函数或基元是无关紧要的。对于基元,将复制它们的值。否则,将复制对象的引用。这就是
与Object.assign()和对象扩展运算符
的情况相同
部分指的是。
关于
上面的代码示例的工作方式与使用.slice()方法将数组复制到a中的方法相同
......确实如此。这是写a.slice()
或[].concat(a)
的简洁方法。有一个相当大的例外。 ES6 rest运算符(以及Array.from(a)
)对所有迭代都有效,不仅适用于数组。
对于对象的深副本,ES6不提供任何新内容,应该手动递归地复制对象(数组)。为解决所有问题,使用经过验证的第三方帮助函数仍然有意义,例如Lodash cloneDeep
。
答案 1 :(得分:3)
男人,程序员在展示实际显示差异的例子时表现得很差。
var a = [[['a', 'b'], ['c', 'd']], 'e'];
var b = [...a];
b[0][0][0] = 'z';
b[1] = 'x';
console.log('a', a);
console.log('b', b);
输出:
a [[["z", "b"], ["c", "d"]], "e"]
b [[["z", "b"], ["c", "d"]], "x"]
注意一些可疑的东西?两个数组[0][0][0]
的值都已更改。这意味着位于[0][0][0]
的两个数组中的对象引用到同一个对象,而不是副本。但是[1]
值不同意味着它确实是副本。
浅拷贝表示第一级是复制,更深层次是引用。
答案 2 :(得分:1)
因此,该示例试图传达的是var b = [...a];
不会展开 a
的内部数组(例如b = [1,2,3]
),而是b
{1}}将[[1],[2],[3]]
。因此,b.shift()
会移除并返回b
的{{1}}的第一个元素,然后第二个[1]
只会从返回的数组中删除shift()
。用一个词1
只能达到你的 spreaded 数组的一个级别,例如...
与var b =[...a]
相同,而不是示例中的var b = [a[0], a[1], a[2]]
答案 3 :(得分:1)
不为内部数组元素创建新数组(对于多维数组):
// One-dimensional array
var a = [1,2,3];
var b = [...a];
a[0]='a';
console.log('a',a);
console.log('b',b);
// expected: b[0] == 1
// got: b[0] == 1
// Multi-dimensional array
var a = [[1], [2], [3]];
var b = [...a];
a[0][0]='a';
console.log('a',a);
console.log('b',b);
// expected: b[0][0] == 1
// got: b[0][0] == 'a'
它的工作方式与slice()
类似,因此您必须遍历数组并为每个维度创建新数组。这是一个简单的例子:
// Multi-dimensional array
var a = [[1], [2], [3]];
var b = (function fn(ar){
return ar.map(el=>Array.isArray(el)&&fn(el)||el)
})(a);
a[0][0]='a';
console.log('a',a);
console.log('b',b);
// expected: b[0][0] == 1
// got: b[0][0] == 1