变量赋值如何在JavaScript中工作?

时间:2009-02-04 00:17:03

标签: javascript

所以我前几天正在玩,只是为了确切了解大规模分配在JavaScript中是如何运作的。

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

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

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

a = b = 'foo';
a = 'bar';
console.log(b);

这几乎是一回事,不是吗?那么这一次,它会返回foo而非bar,正如我对第一个例子的行为所期望的那样。

为什么会这样?

N.B。使用以下代码可以简化此示例:

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

a = 'foo';
b = a;
a = 'bar';
console.log(b);

(我怀疑JavaScript将字符串和整数等原语与哈希值区别对待。哈希值返回指针,而“核心”原语返回自己的副本)

7 个答案:

答案 0 :(得分:109)

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

a = b = {};

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

a.foo = 'bar';

它设置了b.foo,因为ab指向同一个对象。

但是!

如果你这样做:

a = 'bar';

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

在JavaScript中,分配变量和分配属性是两种不同的操作。最好将变量视为对象的指针,当您直接赋值给变量时,您不会修改任何对象,只需将变量重新分配给不同的对象。

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

答案 1 :(得分:26)

你的问题已经被Squeegy满意地回答了 - 它与对象与原语无关,而是在同一引用对象中重新分配变量与设置属性。

答案和评论中似乎有很多关于JavaScript类型的混淆,所以这里是对JavaScript类型系统的一个小介绍:

在JavaScript中,有两种根本不同的值:基元和对象(并且没有“哈希”这样的东西)。

字符串,数字和布尔值以及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

答案 2 :(得分:2)

你或多或少是正确的,除了你所谓的“哈希”实际上只是对象的简写语法。

在第一个示例中, a b 都引用同一个对象。在第二个示例中,您更改 a 以引用其他内容。

答案 3 :(得分:2)

这是我的答案版本:

obj = {a:"hello",b:"goodbye"}
x = obj
x.a = "bonjour"

// now obj.a is equal to "bonjour"
// because x has the same reference in memory as obj
// but if I write:
x = {}
x.a = obj.a
x.b = obj.b
x.a = "bonjour"

// now x = {a:"bonjour", b:"goodbye"} and obj = {a:"hello", b:"goodbye"}
// because x points to another place in the memory

答案 4 :(得分:0)

您将a设置为指向新的字符串对象,而b则指向旧的字符串对象。

答案 5 :(得分:0)

在第一种情况下,您更改变量中包含的对象的某些属性,在第二种情况下,您为变量指定一个新值。这是根本不同的事情。变量ab在某种程度上不是由第一个赋值神奇地链接,它们只包含相同的对象。在第二个示例中也是这种情况,直到您为b变量分配新值。

答案 6 :(得分:0)

区别在于简单类型和对象。

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

复制任何简单类型(如字符串或数字)。

我总是有一个方便的copyArray函数,所以我可以确定我没有为同一个数组创建一堆别名。