zoukankan      html  css  js  c++  java
  • a.x = a = {n:2}

    本文遵守CC BY-SA 3.0

    前言:

      标题真是不知道如何命名,就取最重要的一句话吧。话说最近在看javascript权威指南,感觉对这个语言有种莫名的喜欢。。。这个也应该是一个比较经典的问题了,不是出自此书,据说是jQuery源码中的一个用法,网上找了一阵,stackoverflow上直接是0 results。。可能是问题比较久远,貌似都是10年左右的回答,而且也没有什么让我豁然开朗的解答,倒是在回复中看到了一个思路,于是就顺着想下来了,如果有什么错误,还请斧正。

      先把问题放在这里  

    1 var a = {n:1}
    2 var b = a //暂存a
    3 a.x = a = {n:2} //问题的源头
    4 console.log(a.x)
    5 console.log(b.x)

      想想看,输出结果都为什么值。

    一、梳理

    行号1:创建"{n:1}"对象,并将a指向此地址空间(假设为A);

    行号2:将b指向a指向的地址空间(还是A);

    行号3:

      (1) 在赋值没开始的时候:a.x是给地址A中存储的对象分配了一个新属性x,并分配了地址(假设AX);

      (2) 开始赋值,由于赋值是右结合运算,所以这句话可以看作a.x = (a = {n:2});

      再次分布解析,注意,此时a.x的地址空间是AX,a的地址空间是A,{n:2}被作为新对象被创建,并且分配地址空间(假设B)

      1. 其实之所以混乱就是被变量名迷惑了,只要将变量都看作对地址空间或其内部值的操作就简单明了了,比如:

        a.x = (a = {n:2})可以看作:

        a指向的地址空间被更改成对象{n:2}的地址空间;

        a.x中的a的地址空间,即A地址空间存储的x属性(AX地址中的值)被赋值成{n:2};

      2. 分析结果

        整体赋值完成后,a指向的地址空间更新成C,内部值为{n:2};

        还记得b指向的地址空间吗,就是最初的a指向的A,虽然连续赋值语句没有对b进行操作,但是A这块地址空间却被修改了(被赋予新属性x,值为{n:2})

    行号4: 输出 a.x 为undefined。

    行号5: 输出 b.x 为{n:2}。

    二、再努力一次

      如果看完梳理仍然觉得懵逼,可以尝试这么想:

      可能大家对a = {n:2}这句话没什么问题,实际上,所有皆可看作对象,所有皆可作为引用,于是在连等的语句中,对a.x赋值的时候可以看作是在对A地址空间的x属性进行复制,这个连等操作也实际上是在对各个地址空间的值或属性进行修改,所以,即使我们看到的a被修改了,它最初代表的地址空间没有改变,可以参照下面的例子

      现在有三个杯子(A/B/AX),两个标签(a/b/c),一个标记(x1,x2)

      1. 向杯子A中放入一号小球(n:1),然后将a/b标签都贴在杯子A上,c标签贴在杯子AX上;

      2. 向杯子B中放入二号小球(n:2),

      3. 向A中投入一个x1标记,告诉你可以到杯子AX中察看(a.x的创建),AX中投入一个x2标记,告诉你可以到B中找到二号小球(对a.x赋值);

      4. 将a标签贴到B杯子上面。

      5. 这个时候,看看各个物件的状态,

        (1)a标签贴在了B上,b标签还贴在A上,c标签还贴在AX上;

        (2)A里面有个1号小球(n:1),一个指向AX的x1标记;

        (3)AX里面有个x2标记,指向B;

        (4)B里面有个2号小球(n:2);

      6. 察看结果:

        a.x => B杯子中的x标记(没有,所以undefined)

        b.x => A杯子中的x标记(指向杯子AX,再指向杯子B,发现是个2号小球(n:2));

      注:可能看到这里你还是有疑问,为什么a标签的转移要放到最后一步,明明是应该在中间步骤啊,其实在处理赋值语句的时候,如果你修改了属性(x),那将对该引用指向的地址空间存储的值进行修改,也就是改值而非改引用(杯子没变),而对a的赋值才是对引用的修改(移动a标签),也就是说,做a的赋值的时候代表着移动a标签,而对a.x的赋值则代表着对A杯子的x标记作处理,可以理解成,做赋值之前,a.x就已经代表了对A杯子的操作(与期间a标签是否移动无关),当然,这种逻辑可能只有在连等的时候才会出现。

  • 相关阅读:
    互操作
    Rx基础
    数据流块基础
    C# 一个帮您理解回调函数的例子(新手必看)
    C# 多线程之通过Timer开启线程的例子
    C# 利用委托事件进行窗体间的传值(新手必看)
    C#XML文件操作随笔
    C# 委托学习笔记
    c# 关于抓取网页源码后中文显示乱码的原因分析和解决方法
    c# 异步编程 使用回调函数例子
  • 原文地址:https://www.cnblogs.com/ShuolBDe/p/4489607.html
Copyright © 2011-2022 走看看