这是一个琐碎的小问题,还没有给我带来任何问题(我越想越惊讶),但无论如何都困扰着我,我似乎在其他任何地方都找不到足够的答案。
假设我有两个例子
示例1var foo = [1,2],
bar = foo;
bar[0] = 9;
console.log(foo, bar);
这将输出[9,2][9,2].
示例2var 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在运行时的值但我想将bar初始化为与foo相同的值然后改变bar的值,并且只改变bar的值我该怎么做呢?
在例1中没有进行值复制,但是您将foo
的引用赋值给变量bar
。
现在它们都指向相同的对象(数组,在相同的内存位置),因此当你改变其中一个中的数组项时,它会改变两个变量指向的相同内存位置。
要回答底部的问题,您需要在foo
上复制/克隆,然后将该克隆(这将是一个新的对象实例)分配给bar
。那么您就处于例2中的情况,您可以独立地更改它们。
bar = foo;
相当于说"bar指向与foo相同的东西"
当它们都赋值给[1,2]时,它们都指向不同的元素,所以你可以修改其中一个而不改变另一个。
如果你想修改bar而不改变foo,你应该使用:
var foo = [1,2];
var bar = foo.slice(0);
Javascript中的数组是引用类型。
在示例1中,您有一个数组,有两个变量指向它。如果访问两个变量中的任何一个,将更新底层数组。当你记录它的时候,它和你记录的数组是一样的。
在示例二中,有两个数组,每个数组都有一个指向它的变量。当你访问一个变量时,它将访问相应的Array。如果你想在前一个数组的基础上初始化一个新的数组,而不引用同一个数组,你需要复制变量:
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中的任何对象。对于对象,这被称为cloning
(或deep-cloning
,如果您还想复制所有子对象)。