variables赋值在JavaScript中如何工作?

所以我前些日子只是为了看看JavaScript中的集体分配是如何工作的。

首先,我在控制台中尝试了这个例子:

a = b = {}; a.foo = 'bar'; alert(b.foo); 

结果是“酒吧”显示在一个警报。 这是公平的, ab实际上只是同一个对象的别名。 然后我想,我怎么能使这个例子更简单。

 a = b = 'foo'; a = 'bar'; alert(b); 

这几乎是一回事,不是吗? 那么这次,它会返回foo而不是像我期望的那样从第一个例子的行为中获得。

为什么会发生?

NB这个例子可以通过下面的代码进一步简化:

 a = {}; b = a; a.foo = 'bar'; alert(b.foo); a = 'foo'; b = a; a = 'bar'; alert(b); 

(我怀疑JavaScript会将诸如string和整数之类的原语与哈希值区别开来,哈希值会返回一个指针,而“核心”原语返回它们自己的副本)

在第一个示例中,您正在设置现有对象的属性。 在第二个例子中,您正在分配一个全新的对象。

 a = b = {}; 

ab现在是指向同一个对象的指针。 所以当你这样做时:

 a.foo = 'bar'; 

它也设置b.foo ,因为ab指向相同的对象。

然而!

如果你这样做:

 a = 'bar'; 

你现在说的a指向一个不同的对象。 这对于之前指出的内容没有影响。

在JavaScript中,分配一个variables和分配一个属性是两个不同的操作。 最好把variables看作是指向对象的指针,当你直接指定给variables的时候,你不会修改任何对象,而只是把你的variables重新指向不同的对象。

但是分配一个属性,比如a.foo ,会修改指向的对象。 这当然也会修改所有其他的指向这个对象的引用,因为它们都指向同一个对象。

你的问题已经被Squeegy所满足地回答了 – 它与对象和基元没有任何关系,而是通过重新分配variables与在相同引用对象中设置属性。

在答案和评论中似乎有很多关于JavaScripttypes的混淆,所以下面是对JavaScripttypes系统的一个小的介绍:

在JavaScript中,有两种根本不同的值:基本types和对象(没有像“散列”那样的东西)。

string,数字和布尔值以及nullundefined都是原语,对象是可以具有属性的所有东西。 即使数组和函数是常规的对象,因此可以保持任意的属性。 它们在内部[[Class]]属性上有所不同(函数还有一个名为[[Call]]和[[Construct]]的属性,但是,这就是细节)。

原始值可能像对象一样行为的原因是因为自动装箱,但是原语本身不能拥有任何属性。

这里是一个例子:

 var a = 'quux'; a.foo = 'bar'; document.writeln(a.foo); 

这将输出undefineda保存一个原始值,当赋值foo属性时,该原始值被提升为一个对象。 但是这个新的对象立即被丢弃,所以foo的价值就失去了。

像这样想:

 var a = 'quux'; new String(a).foo = 'bar'; // we never save this new object anywhere! document.writeln(new String(a).foo); // a completly new object gets created 

你或多或less是正确的,除了你所指的“散列”实际上只是对象的简写语法。

在第一个例子中, ab都指向同一个对象。 在第二个例子中,你改变一个引用别的东西。

这里是我的答案版本:

 obj={a:"hello",b:"goodbye"} x=obj xa="bonjour" // now obj.a is equal to "bonjour" // because x has the same reference in memory as obj //but if i write : x={} xa=obj.a xb=obj.b xa="bonjour" // now x={a:"bonjour",b:"goodbye"} and obj={a:"hello",b:"goodbye"} //because x points to another place in the memory 

区别在于简单的types和对象。

任何一个对象(如数组或函数)都是通过引用传递的。

任何简单的types(如string或数字)都会被复制。

我总是有一个copyArray函数方便,所以我可以肯定,我没有创build一堆别名到同一个数组。

你正在设置一个指向一个新的string对象,而B一直指向旧的string对象。

在第一种情况下,您更改variables中包含的对象的某些属性,在第二种情况下,您将新值赋给variables。 这是根本不同的事情。 variablesab在第一次赋值时不会以某种方式神奇地链接,它们只包含相同的对象。 在第二个例子中,情况也是如此,直到给bvariables赋值一个新的值。