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

Chr*_*oyd 96 javascript

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

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

a = b = {};
a.foo = 'bar';
console.log(b.foo);
Run Code Online (Sandbox Code Playgroud)

结果是"警报"显示在警报中.这是公平的,a并且b实际上只是同一对象的别名.然后我想,我怎么能让这个例子更简单.

a = b = 'foo';
a = 'bar';
console.log(b);
Run Code Online (Sandbox Code Playgroud)

这几乎是一回事,不是吗?那么这一次,它foo不会bar像我期望的那样返回第一个例子的行为.

为什么会这样?

注意:使用以下代码可以更简化此示例:

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

a = 'foo';
b = a;
a = 'bar';
console.log(b);
Run Code Online (Sandbox Code Playgroud)

(我怀疑JavaScript将字符串和整数等原语与哈希处理不同.哈希返回指针,而"核心"原语返回自己的副本)

Ale*_*yne 113

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

a = b = {};
Run Code Online (Sandbox Code Playgroud)

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

a.foo = 'bar';
Run Code Online (Sandbox Code Playgroud)

它规定b.foo,以及因为ab指向同一个对象.

然而!

如果你这样做:

a = 'bar';
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 但是字符串有方法和属性,而String的原型肯定可以修改.他们肯定像对象一样. (11认同)
  • 也许字符串在技术上不是javascript类型"Object",但它们可以被认为是OO意义上的对象. (9认同)
  • @ddlshack:正如Christoph解释的那样,这是由于自动装箱.如果你要通过`var foo = new String('foo');`来定义一个字符串,那么_that_将是一个字符串对象(并且`typeof`将确认这一点).但是如果你通过字符串文字声明它,那么它们就是字符串基元.请参阅:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/#Distinction_between_string_primitives_and_String_objects (9认同)
  • "你说现在指的是另一个对象." 不,不要使用单词object.字符串不是JavaScript中的对象. (3认同)
  • @Squeegy:字符串是基元,而不是对象:你不能为字符串赋予任意属性!由于Java中的所谓自动装箱,它们只表现像对象一样 (2认同)

Chr*_*oph 26

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

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

在JavaScript中,有两种根本不同的值:基元和对象(并且没有像'hash'这样的东西).

字符串,数字和布尔值,以及nullundefined是原始类型,对象是可以有属性的一切.甚至数组和函数也是常规对象,因此可以保存任意属性.它们只是内部[[Class]]属性不同(函数还有一个名为[[Call]]和[[Construct]]的属性,但是,嘿,这是详细信息).

原始值可能表现为对象的原因是因为自动装箱,但原语本身不能保存任何属性.

这是一个例子:

var a = 'quux';
a.foo = 'bar';
document.writeln(a.foo);
Run Code Online (Sandbox Code Playgroud)

这将输出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
Run Code Online (Sandbox Code Playgroud)