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

所以前几天我玩了一会儿,就是为了看看 JavaScript 中的大量赋值是如何工作的。

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

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

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

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

这差不多是一回事,不是吗?这一次,它返回的是 foo而不是 bar,正如我从第一个例子的行为中所预期的那样。

为什么会这样?

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

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


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

(我怀疑 JavaScript 对字符串和整数等原语的处理方式不同于散列。散列返回一个指针,而“ core”原语返回它们自己的一个副本)

76316 次浏览

You're more or less correct except that what you're referring to as a "hash" is actually just shorthand syntax for an Object.

In the first example, a and b both refer to the same object. In the second example, you change a to refer to something else.

You are setting a to point to a new string object, while b keeps pointing to the old string object.

In the first case you change some property of the object contained in the variable, in the second case you assign a new value to the variable. That are fundamentally different things. The variables a and b are not somehow magically linked by the first assignment, they just contain the same object. That's also the case in the second example, until you assign a new value to the b variable.

In the first example, you are setting a property of an existing object. In the second example, you are assigning a brand new object.

a = b = {};

a and b are now pointers to the same object. So when you do:

a.foo = 'bar';

It sets b.foo as well since a and b point to the same object.

However!

If you do this instead:

a = 'bar';

you are saying that a points to a different object now. This has no effect on what a pointed to before.

In JavaScript, assigning a variable and assigning a property are 2 different operations. It's best to think of variables as pointers to objects, and when you assign directly to a variable, you are not modifying any objects, merely repointing your variable to a different object.

But assigning a property, like a.foo, will modify the object that a points to. This, of course, also modifies all other references that point to this object simply because they all point to the same object.

The difference is between simple types and objects.

Anything that's an object (like an array or a function) is passed by reference.

Anything that's a simple type (like a string or a number) is copied.

I always have a copyArray function handy so I can be sure I'm not creating a bunch of aliases to the same array.

Your question has already been satisfyingly answered by Squeegy - it has nothing to do with objects vs. primitives, but with reassignment of variables vs. setting properties in the same referenced object.

There seems to be a lot of confusion about JavaScript types in the answers and comments, so here's a small introduction to JavaScript's type system:

In JavaScript, there are two fundamentally different kinds of values: primitives and objects (and there is no thing like a 'hash').

Strings, numbers and booleans as well as null and undefined are primitives, objects are everything which can have properties. Even arrays and functions are regular objects and therefore can hold arbitrary properties. They just differ in the internal [[Class]] property (functions additionally have a property called [[Call]] and [[Construct]], but hey, that's details).

The reason that primitive values may behave like objects is because of autoboxing, but the primitives themselves can't hold any properties.

Here is an example:

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

This will output undefined: a holds a primitive value, which gets promoted to an object when assigning the property foo. But this new object is immediately discarded, so the value of foo is lost.

Think of it like this:

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

here is my version of the answer:

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