纠结的连等赋值

偶的看到一段有意思的代码:

作为一个热衷于“钻牛角尖”的人,楼主对这样的代码很感兴趣,也不禁陷入了思考。so也不要说写这样的代码难维护啥的,纯粹为了思考逻辑。

首先,这是一个连等赋值,而且赋值的是个对象。如果是基本的JavaScript类型,不存在引用,也就不会有类似的问题,但是逻辑是一样的。

赋值过程是怎么样的呢?以上的翻译是,b先赋值5,然后(b=5)会返回所赋的值(也就是5),然后再赋值给a,也就是:

所以最初的代码,可以修改成:

如果是这样,那么以下代码有什么区别:

很明显,结果不一样,继续了解下JavaScript的运算顺序。

输出30,我们猜测JavaScript是从左到右运算的(事实也确实如此)。先取出a在内存中的值(10),然后执行fn函数,返回20(同时改变了a的值),10+20=30。

如果运算过程中有括号啥的,是不是会“智能”地改变运算顺序呢?

输出50,还是从左到右,没有智能地先运算括号里的内容,然后改变a的值,再和a相加。这在JavaScript内核中是怎么实现的?这个我也没有研究过,但是我知道C++等语言是没有这么“智能”的,可以通过堆栈来模拟,比如简单计算器

再回头看这道题,声明一个变量a,指向一个对象{n: 1},然后执行连等。可以肯定的是,a.x和a指向的是同一块内存,我们从左到右运算,a.x实际操作的是a指向的对象,发现没有x这个key,那么就会自动添加,它的值等待右边的运算结果。然后a重新引用了一个对象,并且之前的{n:1}这个对象新的key(x)的value也引用到同一个对象上。大概过程如下图,过程2我把它理解为等待,等待过程3中a的运算结果。

如果要说的稍微“专业”一点,连等是先确定所有变量的指针,再让指针指向那个赋值

事实上,解析器在接受到?a.x = a = {n:2}?这样的语句后,会这样做:

  1. 找到 a 和 a.x 的指针。如果已有指针,那么不改变它。如果没有指针,即那个变量还没被申明,那么就创建它,指向 null。
    a 是有指针的,指向?{n:1};a.x 是没有指针的,所以创建它,指向 null。
  2. 然后把上面找到的指针,都指向最右侧赋的那个值,即?{n:2}

如果理解了,试试这道题吧:

 

参考:

  1. Operator_Precedence
  2. javascript 连等赋值问题
1 收藏 2 评论

可能感兴趣的话题



直接登录
最新评论
  • 按你的理解a.x应该是输出object,内容是{n:2},这样是不对的,a.x是undefined。对应的实际代码应该是这样的:

    var a = {n:1};
    a = {n:2};
    a.x ; // 相当于a.x = undefined
    console.log(a.x);

    • var a = {n:1};
      var b =a;
      console.log( a === b); // true a和b是一个引用
      // a.x = a = {n:2};
      a = {n:2};
      console.log ( a === b ); // false 这个a已经不是上一个a了,是一个新的地址,而b才是上一个a,a和b的指针不同了
      a.x ; // 只是定义了一个属性,并没有赋值操作,因为a = {n:2}也是一个定义过程,当然a.x就是undefined
      // a.x = a = {n:2};相当于var a.x,a={n:2}
      console.log(a.x);

跳到底部
返回顶部