striveCode
striveCode copied to clipboard
一道题目看堆栈内存的演变
说明: 图画的很糙,大家明白意思就好,还有引用赋值是不是这样的,大家可以提出自己的意见和论证。
题目是这样的
var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a.x); //undefined
console.log(b.x); //{n:2}
接下来看下内存堆栈的演变
- 当经过
var a = {n:1};

- 当经过
var a = {n:1};
var b = a;

- 最后一句代码很关键,发生挺多事情
为了理解最后一句,先看下我总结的(自己瞎写的,无从考证),不成文的规定
比如 var a = b = c = d =1; 像这样的、栈里面的赋值是从右向左赋值的(栈是后进先出) 但是如果是引用对象,比如: var a = b = c = d = {n:123} 就是从左往右赋值的(引用是标记)。 一个不成文的约定,记住暂时。
所以上述最后一句代码,咱们可以拆成:
a.x = {n:2} 和
a = {n:2}
- 当经过 a.x = {n:2}

- 最后经过 a = {n:2}, 把 a的指向换成了新的

以上是论证1,可以看出强行加了一个引用赋值是从左往右的(简直就是瞎说),这个可以说是错误的,因为 js赋值操作是
从右到左, 可以查证的地方很多,自行百度。
接下来看另一个论证观点: 每个观点都是可以查证的(不提供链接,自行百度、google);
总结下来两点:
-
运算符优先级
.的优先级高于=, 所以先执行a.x, 堆内存中的{n:1}就会变成{n:1, x:undefined},相应的b.x也变了,因为指向的是同一个对象 -
赋值操作是
从右到左,所以先执行a={n:2},a的引用就被改变了。但是需要特别注意,这个值随后又赋值给了a.x,这时候,其实是第一步的{n:1, x:undefined}那个对象。也就是b.x。
内存演变图如下:
从 a.x = a = {n:2} 开始,上两句都很简单
-
a.x = ;先执行
-
随后赋值动作,从右向左
