一、引子

最近在看别人的博客时无意中看到一个这样的问题

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

这是一个典型的连等赋值问题,是不是发现打印的结果跟自己预料的不太一样,就算一样你能具体讲出内部的执行机制吗?

二、直观理解

咋一看这个表达式,我会本能地把它拆解为这样

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

所以根据这个理解得出的打印结果是

console.log(a.x);  //{n: 2}

显然结果是不对的,那问题出在了哪里呢?要想从原理上解释这个问题,还得首先理解以下几个知识点

三、需要理解的知识点

  • 内存的的运行机制
  • JS引擎的解析过程,从左往右
  • 连等赋值的执行方向,从右往左

放在这个例子中对应的理解就是:

  • a、b这些变量名存储的只是一串指向具体对象的指针,这些指针占用的空间是非常小的,而{n: 1}这些对象才是实实在在存在内存中的值
  • JS引擎在执行到a.x = a = {n:2}这句时,并不是直接的从右往左的执行过程。而是计算机会先从左往右解析各个变量名,转换成变量值(计算机只会记变量值,人的话记变量名)。再从右往左执行赋值。
  • 也就是在这个表达式中第一个a和第二个a指向的都是{n: 1};
    a.x = a = {n:2}
  • 解析完成后,从右往左执行赋值,第二个等号赋值时,a重定向到了{n: 2},第一个等号赋值时,实际上是{n:1}.x={n, 2};

    而这个时候指向{a:1, x:{n:2}}这个值的只有b了
  • 所以a.x的值就变为了undefined,因为a已经重定向赋值为{n:2}了,而b就指向了复合之后的对象

四、理解中的误区及思考

我最开始查了连等赋值的相关文章时,对于以上这些原理的理解是没什么问题的,关键是在理解最后那个赋值过程时,我有过一种理解

a = {n:2};
a.x={n:2};
// 所以此时a= {n:2, x:{n:2}}

产生这种理解的原因是觉得对a的赋值有个先后顺序,但事实上好像是不存在的。我对上面那种从解析赋值角度去理解的核心就是在连等赋值执行过程中,总共分为两步,一步是变量名解析,一步是赋值,然后根据赋值之后的值去看相应的变量名与变量之间的对应关系。

五、参考文档

探究JS中的连等赋值问题的更多相关文章

  1. 【转】千万不要在JS中使用连等赋值操作

    原文链接 千万不要在JS中使用连等赋值操作   目录 前言 赋值顺序? 连续赋值能拆开写么? 后记 前言 文章标题这句话原本是在国外某JavaScript规范里看到的,当时并没有引起足够的重视,直到最 ...

  2. 深入探究js中的隐式变量声明

    前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...

  3. 千万不要在JS中使用连等赋值操作

    前言 文章标题这句话原本是在国外某JavaScript规范里看到的,当时并没有引起足够的重视,直到最近一次出现了bug发现JS里的连等赋值操作的特色(坑). 网上搜索一番发现一个非常好的连等赋值的(来 ...

  4. 深入探究js中无所不在的this

    黄金守则: this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window而当函数被作为某个对象的方法调用时, this等于那个对象. 下面是一些相关实践: --------- ...

  5. 探究JS中对象的深拷贝和浅拷贝

    深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj ...

  6. JS中数组初始化以及赋值

    .指定长度,然后初始化 ); ;index < ;index++){ vArray[index] = index; } 2.不指定长度,然后初始化 var vArray = new Array( ...

  7. js 中的基本类型和引用类型的区别

    js中的基本类型赋值之后,只有值相等的时候,二者才会相等,例如 var  a='123'; var b=a; console.log(a===b); 返回的是true ,说明他们是相等的, 此时改变a ...

  8. js中的offsetLeft和style.left

    (1)style.left是带单位"px"的,而offsetLeft没有单位,另外,style.left必须是内联样式,或者在JS中通过style.left赋值,否则取得的将为空字 ...

  9. 二、js中基础知识

    该篇文章主要是强化一下自己javaScript的基础,让写代码变得更轻松些.基础好的请忽略.    JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解 ...

随机推荐

  1. The 15th UESTC Programming Contest Preliminary B - B0n0 Path cdoj1559

    地址:http://acm.uestc.edu.cn/#/problem/show/1559 题目: B0n0 Path Time Limit: 1500/500MS (Java/Others)    ...

  2. 【Linux学习】1.Linux基础知识

    记录学习Linux 系统的相关知识点,欢迎大家拍砖交流,一起成长:QQ:2712192471 作者背景:前端开发工程师 | Python | web安全爱好者 一,Windows系统下 Linux 的 ...

  3. iOS开发之HelloKit代码片段

    完整代码托管:https://github.com/1042710553/HelloKit.git /************************/plist/****************** ...

  4. JS等比例缩放图片,限定最大宽度和最大高度

    JS等比例缩放图片,限定最大宽度和最大高度 JavaScript //图片按比例缩放 var flag=false; function DrawImage(ImgD,iwidth,iheight){ ...

  5. 20145301《Java程序设计》实验报告一:Java开发环境的熟悉

    20145301<Java程序设计>实验报告一:Java开发环境的熟悉 课程:Java程序设计 实验名称:Java开发环境的熟悉 实验目的与要求: 1.没有Linux基础的同学建议先学习& ...

  6. 20145327 《Java程序设计》第三周学习总结

    20145327 <Java程序设计>第三周学习总结 教材学习内容总结 对象:存在的具体实体,具有明确的状态和行为. 类:具有相同属性和行为的一组对象的集合,用于组合各个对象所共有操作和属 ...

  7. java语言基本环境搭建

    从放假开始,就开始路陆陆续续了解关于java语言的学习.首先从语言编辑环境就和以前学习的c语言会有些不同,对java语言的学习也有了很大很多新的认识. 首先从官网上下载jdk,按照娄老师给我们的操作提 ...

  8. jdbctemplate中的queryForInt方法

    今天才发现,原来spring 3.2.2之后,jdbctemplate中的queryForInt已经被取消了! 看下代码: 原来是这样写的: String sql = "SELECT cou ...

  9. 异步:asyncio和aiohttp的一些应用(2)

    转自:原文链接:http://www.cnblogs.com/ssyfj/p/9222342.html 1.aiohttp的简单使用(配合asyncio模块) import asyncio,aioht ...

  10. 【Semantic Segmentation】U-Net: Convolutional Networks for Biomedical Image Segmentation 论文解析(转)

    目录 0. 前言 1. 第一篇 2. 第二篇 3. 第三篇keras实现 4. 一篇关于U-Net的改进 0. 前言   今天读了U-Net觉得很不错,同时网上很多很好很详细的讲解,因此就不再自己写一 ...