:P 你正在深入纠缠不清的细节,我很高兴你问了这个问题,因为最终你会更加明智。
不要从指针的角度来看待它,因为我认为那是让你感到困惑的地方。相反,以堆(或者说“内存”)和符号表的角度来考虑它。
让我们从你代码的前几行开始:
var a, b;
a = {}
b = a;
你所做的是在堆上创建了一个对象和两个符号表中的符号。其大致如下:
符号表:
+
| Symbol | Memory Location |
+
| a | 0x400000 |
+
| b | 0x400000 |
+
堆(Heap):
+
| Location | Value |
+
| 0x400000 | <object val 1> |
+
事情变得有趣的地方在于:对象拥有自己的“符号表”(通常只是哈希表,但称其为符号表可以使其更清晰)。
现在,在您的下一条语句之后,您需要考虑三件事:全局符号表、<object val 1>
的符号表和堆。
运行以下代码:
a['one'] = {}
现在的情况如下:
全局符号表:
+
| Symbol | Memory Location |
+
| a | 0x400000 |
+
| b | 0x400000 |
+
<object val 1>
的符号表
+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
| one | 0x400004 |
+--------+-----------------+
堆(heap):
+
| Location | Value |
+
| 0x400000 | <object val 1> |
+
| 0x400004 | <object val 2> | <
+
.
现在你运行了以下代码:
a = a['one']
这应该是一个微不足道的更改。结果如下:
全局符号表:
+
| Symbol | Memory Location |
+
| a | 0x400004 |
+
| b | 0x400000 |
+
<object val 1>
的符号表
+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
| one | 0x400004 |
+--------+-----------------+
堆(Heap):
+
| Location | Value |
+
| 0x400000 | <object val 1> |
+
| 0x400004 | <object val 2> |
+
沿着内存地址向堆区查找,有助于理解为什么会得到你所看到的输出。
现在情况变得更加有趣,因为你正在执行以下操作:
a['two'] = 2;
好的,让我们一步步来。
a
指向内存位置 0x400004
,该位置包含 <object val 2>
<object val 2>
是一个空对象,因此它的符号表一开始是空的
- 通过执行这行代码,我们将变量 'two' 添加到
<object val 2>
的符号表中。
如果你还没有看够这些图表,那你很快就会疲倦。现在的情况如下:
全局符号表:
+
| Symbol | Memory Location |
+
| a | 0x400004 |
+
| b | 0x400000 |
+
<object val 1>
的符号表
+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
| one | 0x400004 |
+--------+-----------------+
<object val 2>
的符号表
+
| Symbol | Memory Location |
+
| two | 0x400008 |
+
堆(Heap):
+
| Location | Value |
+
| 0x400000 | <object val 1> |
+
| 0x400004 | <object val 2> |
+
| 0x400008 | 2 (literal val) | <
+
如果你勤奋地花时间跟踪内存位置,你会发现你的浏览器显示了正确的输出。
b
指向的对象来改变原始变量a
指向的对象,但你绝对不能这样做(无论是否在函数中)。 - nnnnnnb
来改变a
指向的对象的指针是如何实现的呢?看起来a
和b
是相互独立的引用,就像指针一样,而且它似乎仅通过引用传递,只是不传递变量的引用,而是传递变量所指向的东西的引用。 - Seth Carnegieb
来改变a
指向的位置 - “这是绝对不可能的”。JavaScript 绝对不会按引用传递。所以你说a
和b
就像独立的指针,可能指向相同的对象,也可能不是。(但除了讨论函数参数之外,使用“传递”这个词没有意义。) - nnnnnn