itstrive / striveCode

some demo and js Knowledge points records :cn: :cloud: :snowflake:
108 stars 83 forks source link

一道题目看堆栈内存的演变 #19

Open itstrive opened 5 years ago

itstrive commented 5 years ago

说明: 图画的很糙,大家明白意思就好,还有引用赋值是不是这样的,大家可以提出自己的意见和论证。

题目是这样的

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};

image

var a = {n:1};
var b = a;

image

为了理解最后一句,先看下我总结的(自己瞎写的,无从考证),不成文的规定

比如 var a = b = c = d =1; 像这样的、栈里面的赋值是从右向左赋值的(栈是后进先出) 但是如果是引用对象,比如: var a = b = c = d = {n:123} 就是从左往右赋值的(引用是标记)。 一个不成文的约定,记住暂时。

所以上述最后一句代码,咱们可以拆成:

a.x = {n:2} 和
a = {n:2}

image

image

itstrive commented 5 years ago

以上是论证1,可以看出强行加了一个引用赋值是从左往右的(简直就是瞎说),这个可以说是错误的,因为 js赋值操作是 从右到左, 可以查证的地方很多,自行百度。

接下来看另一个论证观点: 每个观点都是可以查证的(不提供链接,自行百度、google);

总结下来两点:

  1. 运算符优先级 .的优先级高于 =, 所以先执行 a.x, 堆内存中的 {n:1} 就会变成 {n:1, x:undefined},相应的 b.x也变了,因为指向的是同一个对象

  2. 赋值操作是从右到左,所以先执行 a={n:2},a的引用就被改变了。但是需要特别注意,这个值随后又赋值给了 a.x,这时候,其实是第一步的 {n:1, x:undefined} 那个对象。也就是 b.x

内存演变图如下:

a.x = a = {n:2} 开始,上两句都很简单