探究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一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解 ...
随机推荐
- Linux系统——本地定制化yum仓库部署
1)开启yum仓库配置文件 /etc/yum.conf的keepcache功能 (开启一个新的虚拟机) 将keepcache=0改为1,修改配置文件后重新清空缓存(1默认下载的安装包不删除,才可以实现 ...
- DevStore教你如何玩转饥饿营销?
首先我们必需知道: 所谓“饥饿营销”,是指商品提供者有意调低产量,以期达到调控供求关系.制造供不应求“假象”.维持商品较高售价和利润率的目的. 饥饿营销”营销方式,其通常的步骤: 1.引起关注.首先是 ...
- JAVA垃圾回收机
垃圾回收基本算法 串型回收和并行回收 串行回收始终在一个CPU上执行回收操作.并行回收则将回收任务分为好几步,每步使用不同的CPU执行,这样加快了执行速度,有点像流水线作业. 并发执行和暂停应用程序 ...
- eclipse调试程序界面简单介绍使用
右键程序 Debug 运行后 如下图:
- opencv图像处理之在手机上实现背景虚化
http://m.blog.csdn.net/blogercn/article/details/75004162 1.高端数码相机都具有背景虚化功能.背景虚化就是使景深变浅,使焦点聚集在主题上.一般的 ...
- 20145216史婧瑶《Java程序设计》第8周学习总结
20145216 <Java程序设计>第8周学习总结 教材学习内容总结 第十五章 通用API 15.1 日志 java.util.logging 包提供了日志功能相关类与接口,不必额外配置 ...
- 20145321 《Java程序设计》第7周学习总结
20145321 <Java程序设计>第7周学习总结 教材学习内容总结 第十三章 时间与日期 13.1 认识时间与日期 1.格林威治时间(GMT) 观察太阳得来 2.世界时(UT) 3.国 ...
- [Deep Learning] 神经网络基础【转】
本文转载自:http://www.cnblogs.com/maybe2030/p/5597716.html 阅读目录 1. 神经元模型 2. 感知机和神经网络 3. 误差逆传播算法 4. 常见的神经网 ...
- Oracle18c创建不带C##的用户
18c数据库分两种数据库CDB(容器数据库).PDB(可插拔数据库) 数据库安装完成之后,默认是CDB 创建一个用户,必须要用C##开头,但使用PDB没有这个限制 1. 先查看PDB数据库servic ...
- 关于C#中的垃圾回收
http://cnn237111.blog.51cto.com/2359144/1343004 GC.Collect如何影响垃圾回收 主要是 //GC.Collect(); //GC.WaitF ...