传播会创建浅拷贝吗?

时间:2018-04-26 20:13:22

标签: typescript ecmascript-6 deep-copy shallow-copy

根据给定的here示例,

let first:number[] = [1, 2];
let second:number[] = [3, 4];

let both_plus:number[] = [0, ...first, ...second, 5];
console.log(`both_plus is ${both_plus}`);
first[0] = 20;
console.log(`first is ${first}`);
console.log(`both_plus is ${both_plus}`);
both_plus[1]=30;
console.log(`first is ${first}`);
console.log(`both_plus is ${both_plus}`);

Spreading显示一个深层副本,因为所有三个数组都有它自己的副本,基于以下输出:

both_plus is 0,1,2,3,4,5
first is 20,2
both_plus is 0,1,2,3,4,5
first is 20,2
both_plus is 0,30,2,3,4,5

Documentation说:传播会创建firstsecond 的浅表副本。我怎么理解这个?

3 个答案:

答案 0 :(得分:2)

浅拷贝意味着firstsecond中的所有元素仅添加到新数组(新副本)中。深层复制意味着首先复制firstsecond中的所有元素,然后将其添加到新数组中。

区别在于元素本身是否在添加到新数组之前被复制到新对象中。

使用基元,如数字,实际上不可能说明差异,但如果使用对象,差异就很明显了。

说你有这样的事情:

let first = [{foo: 'bar'}];
let second = [{fizz: 'buzz'}];
let both = [...first, ...second];

由于传播导致浅拷贝,您可以期望相关对象通过相等测试:

first[0] === both[0]; // true
second[0] === both[1]; // true

但是如果传播导致深层复制,你会期望相等测试失败:

first[0] === both[0]; // false
second[0] === both[1]; // false

答案 1 :(得分:2)

在您的情况下,浅拷贝和深拷贝是相同的。对于仅包含基元的数组,它们将始终相同。当数组包含其他对象时,您只会注意到差异。

Javascript是按值传递的,因此当数组被浅层复制时(例如使用spread),原始数组中的每个值都会被复制到新数组中。在基元的情况下,直接复制值,对其进行的更改对原始值没有影响。

但是,当数组包含对象时,每个值本身都是对其他内容的引用。因此,即使引用已复制到新数组,它仍然指向与原始数组中的引用相同的内容。因此,虽然改变新数组不会改变原始数组,但改变数组元素会影响原始数组。

以下是一个例子:

const objArray = [{foo: "bar"}];
const shallowCopy = [...objArray];

// Changing the array itself does not change the orignal. Note the
// original still only has one item, but the copy has two:
shallowCopy.push({foo: "baz"});
console.log("objArray after push:", objArray);
console.log("shallowCopy after push:", shallowCopy);

// However, since shallowCopy[0] is a reference pointing to the same object
// as objArray[0], mutating either will change the other:
shallowCopy[0].foo = "something else";
console.log("objArray after mutation:", objArray);
console.log("shallowCopy after mutation:", shallowCopy);

答案 2 :(得分:1)

传播会导致浅拷贝

const a = [{x: 1}, {y: 1}];
const b = a;

const c = [...a, ...b];
console.log(c); // [{x: 1}, {y: 1}, {x: 1}, {y: 1}]

a[1]['y'] = 5;
console.log(c); // [{x: 1}, {y: 5}, {x: 1}, {y: 5}]