测试代码如下:
var a = { n: 1 };
var b = a;
a.x = a = { n: 2 };
console.log(a);
console.log(b);
console.log(a.n);
相信绝大多数人第一反应如下:
- 开辟内存空间* 存储
{ n: 1 }
并将变量a指向该内存空间; - 变量
b
指向第一步内存空间*; -
a = { n: 2 }
开辟新的内存空间**{n: 2}
并将变量a
指向该内存空间; -
a.x = a
将a
所指向的内存空间**中的{n: 2}
添加新的属性x
,并赋值形成{ n: 2, x: { n: 2 } }
;
基于如上分析,打印结果为:
{ n: 2, x: { n: 2 } }
{ n: 1 }
{ n: 2 }
然而,世事难料,实际打印打印结果如下:
{ n: 2 }
{ n: 1, x: { n: 2 } }
2
正确执行顺序如下:
- 开辟内存空间* 存储
{ n: 1 }
并将变量a指向该内存空间; - 变量
b
指向第一步内存空间*; - 解析变量
a.x
,此时指向内存空间*{ n: 1 }
,解析变量a
,为指针; - 开始赋值,同上分析过程3;
- 开始赋值,将内存空间*
{ n: 1 }
更改为{ n: 1, x: { n: 2 } }
;
另,由于b始终指向内存空间* 故过程5的更改将直接作用于它。