Spreading 会创建浅拷贝吗?

Does Spreading create 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}`);

展开显示了一个深拷贝,因为所有三个数组都有自己的副本,基于以下输出:

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 的浅拷贝。我怎么理解这个?

浅拷贝意味着 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

在你的例子中,浅拷贝和深拷贝是一样的。对于仅包含基元的数组,它们将始终相同。只有当您的数组包含其他对象时,您才会注意到差异。

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);

在浅拷贝中传播结果

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}]