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)分配给变量
现在它们都指向相同的对象(数组,在相同的内存位置),因此当您更改其中一个数组项时,它会更改两个变量指向的相同内存位置。
要回答底部的问题,您需要复制/克隆
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中的任何对象。对于对象,如果您还想复制所有子对象,则称为
线
1 | bar = foo; |
相当于说"bar指向与foo相同的东西"
尽管将它们都指定给[1,2],但它们都指向不同的元素,因此您可以修改一个元素而不链接另一个元素。
如果要在不更改foo的情况下修改栏,应使用:
1 2 | var foo = [1,2]; var bar = foo.slice(0); |