zoukankan      html  css  js  c++  java
  • 奇特的JavaScript连续赋值运算

    一、引子:

    var a = {n:1};
    a.x = a = {n:2};
    alert(a.x); // --> undefined

      以上第二句 a.x = a = {n:2} 是一个连续赋值表达式。这个连续赋值表达式在引擎内部究竟发生了什么?是如何解释的?

    二、猜想

      猜想1:从左到右赋值,a.x 先赋值为{n:2},但随后 a 赋值为 {n:2},即 a 被重写了,值为 {n:2},新的 a 没有 x属性,因此为undefined。步骤如下
    1, a.x = {n:2};
    2, a = {n:2};
    这种解释得出的结果与实际运行结果一致,貌似是对的。注意猜想1中 a.x 被赋值过。
      猜想2:从右到左赋值,a 先赋值为{n:2},a.x 发现 a 被重写后(之前a是{a:1}),a.x = {n:2} 引擎限制a.x赋值,忽略了。步骤如下:
    1, a = {n:2};
    2, a.x 未被赋值{n:2}
    等价于 a.x = (a = {n:2}),即执行了第一步,这样也能解释a.x为undefined了。注意猜想2中a.x压根没被赋值过。

    三、证明

      上面两种猜想相信多数人都有,有人认为是猜想1, 有人认为是猜想2。其实都错了,我忽略了引用的关系。如下,加一个变量b,指向a。

    var a = {n:1};
    var b = a; // 暂存a
    a.x = a = {n:2};
    alert(a.x);// --> undefined
    alert(b.x);// --> [object Object]

      发现 a.x 仍然是undefined,神奇的是 b.x 并未被赋值过(比如:b.x={n:2}),却变成了[object Object]。b 是指向 a({n:1})的,只有a.x = {n:2}执行了才说明 b 是有 x 属性的。

      实际执行过程:从右到左,a 先被赋值为{n:2},随后a.x被赋值{n:2}。等价于:a.x = (a = {n:2});  与猜想2的区别在于 a.x 被赋值了,猜想2中并未赋值。

      最重要的区别,第一步 a = {n:2} 的 a 指向的是新的对象{n:2} , 第二步 a.x = {n:2} 中的 a 是 {a:1}

      即在这个连等语句中,a.x 中的a指向的是 {n:1},a 指向的是 {n:2}。如下图:

      

    四:解惑

      这篇写完,或许部分人看完还是晕晕的,因为里面的文字描述实在是绕口。最初我在理解这个连等赋值语句时,认为结果为:{n:2},实际却不是这样的。

      a指向的对象已经不同了,引擎也没有限制a.x的重写。

    var a = {n:1};
    var b = a;
    a.x = a = {n:2};
    console.log(a,a.x);
    console.log(b);
    //Object {n: 2}   undefined
    //Object {n: 1, x: Object}  Object {n: 2}

      理解:第一个a.x的a就近原则,指向的是第一行声明的a;console.log(a.x)里的a.x相当于a被重新赋值,就近原则,a指向的是{n:2},并没有x属性,故为undefined。

    五:结束

      以另一个连续赋值题结束。fun执行后,这里的 变量 b 溢出到fun外成为了全局变量。想到了吗?

      思考:要记住这种连续赋值,后面的变量是一种隐式声明即可。

    function fun(){
        var a = b = 5;
    }
    fun();
    console.log(a); // --> 报错:a is not defined
    console.log(b); // --> 5
  • 相关阅读:
    SCOI2014 方伯伯的OJ onlinejudge
    【JZOJ4854】【NOIP2016提高A组集训第6场11.3】小澳的坐标系
    【JZOJ4847】【NOIP2016提高A组集训第5场11.2】夕阳
    【JZOJ4846】【NOIP2016提高A组集训第5场11.2】行走
    【JZOJ4845】【NOIP2016提高A组集训第5场11.2】寻找
    【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集
    【JZOJ4840】【NOIP2016提高A组集训第4场11.1】小W砍大树
    【JZOJ4835】【GDOI2017模拟10.31】量化交易
    【JZOJ4831】【NOIP2016提高A组集训第3场10.31】方程式
    【JZOJ4832】【NOIP2016提高A组集训第3场10.31】高维宇宙
  • 原文地址:https://www.cnblogs.com/goloving/p/7712686.html
Copyright © 2011-2022 走看看