variables赋值在JavaScript中如何工作?
所以我前些日子只是为了看看JavaScript中的集体分配是如何工作的。
首先,我在控制台中尝试了这个例子:
a = b = {}; a.foo = 'bar'; alert(b.foo);
结果是“酒吧”显示在一个警报。 这是公平的, a
和b
实际上只是同一个对象的别名。 然后我想,我怎么能使这个例子更简单。
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 = {};
a
和b
现在是指向同一个对象的指针。 所以当你这样做时:
a.foo = 'bar';
它也设置b.foo
,因为a
和b
指向相同的对象。
然而!
如果你这样做:
a = 'bar';
你现在说的a
指向一个不同的对象。 这对于之前指出的内容没有影响。
在JavaScript中,分配一个variables和分配一个属性是两个不同的操作。 最好把variables看作是指向对象的指针,当你直接指定给variables的时候,你不会修改任何对象,而只是把你的variables重新指向不同的对象。
但是分配一个属性,比如a.foo
,会修改指向的对象。 这当然也会修改所有其他的指向这个对象的引用,因为它们都指向同一个对象。
你的问题已经被Squeegy所满足地回答了 – 它与对象和基元没有任何关系,而是通过重新分配variables与在相同引用对象中设置属性。
在答案和评论中似乎有很多关于JavaScripttypes的混淆,所以下面是对JavaScripttypes系统的一个小的介绍:
在JavaScript中,有两种根本不同的值:基本types和对象(没有像“散列”那样的东西)。
string,数字和布尔值以及null
和undefined
都是原语,对象是可以具有属性的所有东西。 即使数组和函数是常规的对象,因此可以保持任意的属性。 它们在内部[[Class]]属性上有所不同(函数还有一个名为[[Call]]和[[Construct]]的属性,但是,这就是细节)。
原始值可能像对象一样行为的原因是因为自动装箱,但是原语本身不能拥有任何属性。
这里是一个例子:
var a = 'quux'; a.foo = 'bar'; document.writeln(a.foo);
这将输出undefined
: a
保存一个原始值,当赋值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是正确的,除了你所指的“散列”实际上只是对象的简写语法。
在第一个例子中, a和b都指向同一个对象。 在第二个例子中,你改变一个引用别的东西。
这里是我的答案版本:
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。 这是根本不同的事情。 variablesa
和b
在第一次赋值时不会以某种方式神奇地链接,它们只包含相同的对象。 在第二个例子中,情况也是如此,直到给b
variables赋值一个新的值。