关于javascript:为什么复杂类型适用于参考值

Why do complex types work on a reference value

这是一个还没有给我带来任何问题的小问题(这越来越让我惊讶,我想得越多),但困扰我的任何方式,我似乎找不到足够的答案在其他任何地方。

假设我有两个例子

例1

1
2
3
4
5
var foo = [1,2],
    bar = foo;

bar[0] = 9;
console.log(foo, bar);

这将输出[9,2][9,2]。

例2

1
2
3
4
5
var foo = [1,2],
    bar = [1,2];

bar[0] = 9;
console.log(foo, bar);

这将输出[1,2][9,2]。

从技术的角度来看,例1和例2之间的区别是什么?

在示例1中,您似乎正在将bar初始化为foo的值,但只更改bar的值。为什么示例1中的bar[0]=9也会更改存储在foo中的值?

另一方面,如果我真的想这么做呢?假设我不知道foo的值在运行时是什么,但我想初始化与foo相同的值的bar,然后更改bar和only bar的值,我该怎么做?


在示例1中,没有进行值复制,但是您将EDOCX1的引用(0)分配给变量bar

现在它们都指向相同的对象(数组,在相同的内存位置),因此当您更改其中一个数组项时,它会更改两个变量指向的相同内存位置。

要回答底部的问题,您需要复制/克隆foo,然后将该克隆(将是新的对象实例)分配给bar。然后是示例2中的情况,您可以独立地更改它们。


javascript中的数组是引用类型。

在示例1中,您有一个数组,其中有两个变量指向它。如果您访问两个变量中的任何一个,您将更新基础数组。当您记录它时,它是您记录的同一个数组。

在示例2中,有两个数组,每个数组都有一个指向它的变量。当您访问一个变量时,它将访问相应的数组。

如果要在不引用同一数组的情况下基于上一个数组初始化新数组,则需要复制变量:

1
2
3
4
5
6
7
8
9
var foo = [1, 2],
    bar = [];

for (var i = 0; i<foo.length;i++){
    bar.push(foo[i]);
}

// or a shortcut:
bar = foo.slice(0);

这适用于数组,也适用于JS中的任何对象。对于对象,如果您还想复制所有子对象,则称为cloningdeep-cloning


线

1
bar = foo;

相当于说"bar指向与foo相同的东西"

尽管将它们都指定给[1,2],但它们都指向不同的元素,因此您可以修改一个元素而不链接另一个元素。

如果要在不更改foo的情况下修改栏,应使用:

1
2
var foo = [1,2];
var bar = foo.slice(0);