admin管理员组文章数量:1201412
From mdn: Spread Syntax
Note: Typically the spread operators in ES2015 goes one level deep while copying an array. Therefore, they are unsuitable for copying multidimensional arrays. It's the same case with Object.assign() and Object spread syntax. Look at the example below for a better understanding.
var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Now array b is: [[2], [3]]
What is the point of the above statement? The above code sample works just the same as if you'd copied the array in a to b using the .slice() method. I tried adding another dimension to the array here: and things still worked as expected.
So why is the spread syntax unsuitable for copying multidimensional arrays?
I'd appreciate any help.
EDIT:
Reading the answers by estus and vol7ron helped me figure things out. Basically, as estus points out technically there are just arrays inside arrays rather than multidimensional arrays.
And as vol7ron explains only the first level of the array is copied so the objects in memory remain the same for any further nested elements.
I was also wrong to suspect that using the spread syntax was supposed to behave any differently than the slice operator
From mdn: Spread Syntax
Note: Typically the spread operators in ES2015 goes one level deep while copying an array. Therefore, they are unsuitable for copying multidimensional arrays. It's the same case with Object.assign() and Object spread syntax. Look at the example below for a better understanding.
var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Now array b is: [[2], [3]]
What is the point of the above statement? The above code sample works just the same as if you'd copied the array in a to b using the .slice() method. I tried adding another dimension to the array here: https://repl.it/HKOq/2 and things still worked as expected.
So why is the spread syntax unsuitable for copying multidimensional arrays?
I'd appreciate any help.
EDIT:
Reading the answers by estus and vol7ron helped me figure things out. Basically, as estus points out technically there are just arrays inside arrays rather than multidimensional arrays.
And as vol7ron explains only the first level of the array is copied so the objects in memory remain the same for any further nested elements.
I was also wrong to suspect that using the spread syntax was supposed to behave any differently than the slice operator
Share Improve this question edited Sep 7, 2018 at 1:02 Patrick Roberts 51.8k10 gold badges116 silver badges162 bronze badges asked Apr 15, 2017 at 2:55 Gwater17Gwater17 2,3143 gold badges23 silver badges45 bronze badges 2 |5 Answers
Reset to default 16Man, programmers are really poor at displaying examples that actually show the difference.
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);
This outputs:
a [[["z", "b"], ["c", "d"]], "e"]
b [[["z", "b"], ["c", "d"]], "x"]
Notice something fishy? Both arrays [0][0][0]
value was changed. Meaning that the object sitting at [0][0][0]
in both arrays are referenced to the same object, and is not a copy. However the [1]
values are different meaning that it is indeed a copy.
Shallow copy means the first level is copied, deeper levels are referenced.
Arrays are objects, and [...a]
creates a shallow copy of a
array object.
For the language itself there are no multidimentional arrays - there are another arrays inside an array. It doesn't matter if contains arrays, plain objects, functions or primitives. For primitives, their values will be copied. Otherwise, the references to objects will be copied. This is what
It's the same case with Object.assign() and Object spread operators
part refers to.
And regarding
The above code sample works just the same as if you'd copied the array in a to b using the .slice() method
...it truly does. This is a neater way to write a.slice()
or [].concat(a)
. With a considerable exception. ES6 rest operator (as well as Array.from(a)
) works equally for all iterables, not just for arrays.
For a deep copy of an object ES6 offers nothing new, an object (which an array is) should be recursively copied by hand. To address all the concerns it still makes sense to use proven third-party helper functions, such as Lodash cloneDeep
.
New arrays are not created for internal array elements (for multi-dimensional array):
// 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'
It works like slice()
, so you would have to traverse the array and create new arrays for each dimension. Here's one quick example:
// 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
So what the example is trying to convey is that var b = [...a];
will not unroll the inner arrays of a
(e.g b = [1,2,3]
), but instead, b
will be [[1],[2],[3]]
. So b.shift()
removes and returns the first element of b
which is [1]
, then the second shift()
just removes 1
from that returned array. In one word ...
only reaches one level down into your spreaded array, e.g. var b =[...a]
is equivelent to var b = [a[0], a[1], a[2]]
, not var b = [ a[0][0], a[1][0], a[2][0] ]
in the example
There is this structuredClone() function available with JS Vanilla. please check the doc @ the following address:https://developer.mozilla.org/en-US/docs/Web/API/structuredClone. This is usable for creating a Deep Copy.
本文标签: javascriptWhy is a spread element unsuitable for copying multidimensional arraysStack Overflow
版权声明:本文标题:javascript - Why is a spread element unsuitable for copying multidimensional arrays? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738597521a2101870.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
...
is not an operator! – Felix Kling Commented Apr 15, 2017 at 3:49...
is a punctuator that is used in rest and spread syntaxes. – RobG Commented Apr 15, 2017 at 4:20