探究JS中的连等赋值问题
一、引子
最近在看别人的博客时无意中看到一个这样的问题
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中的连等赋值问题的更多相关文章
- 【转】千万不要在JS中使用连等赋值操作
原文链接 千万不要在JS中使用连等赋值操作 目录 前言 赋值顺序? 连续赋值能拆开写么? 后记 前言 文章标题这句话原本是在国外某JavaScript规范里看到的,当时并没有引起足够的重视,直到最 ...
- 深入探究js中的隐式变量声明
前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...
- 千万不要在JS中使用连等赋值操作
前言 文章标题这句话原本是在国外某JavaScript规范里看到的,当时并没有引起足够的重视,直到最近一次出现了bug发现JS里的连等赋值操作的特色(坑). 网上搜索一番发现一个非常好的连等赋值的(来 ...
- 深入探究js中无所不在的this
黄金守则: this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window而当函数被作为某个对象的方法调用时, this等于那个对象. 下面是一些相关实践: --------- ...
- 探究JS中对象的深拷贝和浅拷贝
深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj ...
- JS中数组初始化以及赋值
.指定长度,然后初始化 ); ;index < ;index++){ vArray[index] = index; } 2.不指定长度,然后初始化 var vArray = new Array( ...
- js 中的基本类型和引用类型的区别
js中的基本类型赋值之后,只有值相等的时候,二者才会相等,例如 var a='123'; var b=a; console.log(a===b); 返回的是true ,说明他们是相等的, 此时改变a ...
- js中的offsetLeft和style.left
(1)style.left是带单位"px"的,而offsetLeft没有单位,另外,style.left必须是内联样式,或者在JS中通过style.left赋值,否则取得的将为空字 ...
- 二、js中基础知识
该篇文章主要是强化一下自己javaScript的基础,让写代码变得更轻松些.基础好的请忽略. JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解 ...
随机推荐
- 【转】阿里巴巴技术专家杨晓明:基于Hadoop技术进行地理空间分析
转自:http://www.csdn.net/article/2015-01-23/2823687-geographic-space-base-Hadoop [编者按]交通领域正产生着海量的车辆位置点 ...
- ansible一些基本操作
一.介绍 特性 (1).no agents:不需要在被管控主机上安装任何客户端: (2).no server:无服务器端,使用时直接运行命令即可: (3).modules in any languag ...
- C#数组的Map、Filter、Reduce操作
在Javascript.Python等语言里,Map.Filter和Reduce是数组的常用方法,可以让你在实现一些数组操作时告别循环,具有很高的实用价值.它们三个的意义大家应该都清楚,有一个十分形象 ...
- Linux查看端口占用情况,并强制释放占用的端口
1.查找被占用的端口 netstat -tln netstat -tln | grep 8080 netstat -tln 查看端口使用情况,而netstat -tln | grep 8080则是只查 ...
- [转]关于Navicat和MYSQL字符集不统一出现的中文乱码问题
原文链接:关于Navicat和MYSQL字符集不统一出现的中文乱码问题 最近遇到一串关于MYSQL中文乱码的问题,问题背景是这样的: 在此之前,服务器上安装好MySQL之后就立马重新配置了字符集为ut ...
- 在python3下使用OpenCV做离散余弦变换DCT及其反变换IDCT
对图像处理经常用到DCT, Python下有很多带有DCT算法包, 这里使用OpenCV的DCT做变换, 并简单置0部分数据, 再查看反变换图像的效果. import numpy as np impo ...
- Python面试题之functools模块
文档 地址 functools.partial 作用: functools.partial 通过包装手法,允许我们 "重新定义" 函数签名 用一些默认参数包装一个可调用对象,返回结 ...
- BeanFactory笔记
BeanFactory是一个工厂接口,在spring中,BeanFactory是IOC容器的核心接口,功能是:实例化.定位.配置应用程序中的对象及建立这些对象间的依赖,但它并不是IOC容器的具体实现, ...
- 20145314郑凯杰《信息安全系统设计基础》第7周学习总结 part B
20145314郑凯杰<信息安全系统设计基础>第7周学习总结 part B 上篇博客反思与深入 首先根据本周第一篇博客,娄老师给我的评论,我开始进行局部性的深入研究: 分为两个步骤,一是知 ...
- 20145314郑凯杰 《Java程序设计》第3周学习总结
20145314郑凯杰 <Java程序设计>第3周学习总结 所有代码均已托管 地址https://git.oschina.net/qiaokeli26/codes 按照下面程序结果中的代码 ...