写了10年的Javascript也未必全了解的连续赋值运算


Posted in Javascript onMarch 25, 2011

一、引子

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

这是蔡蔡在看 jQuery源码 时发现这种写法的。以上第二句 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}。
1, a = {n:2};
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:2};

a.x 中的a指向的是 {n:1},a 指向的是 {n:2}。如下图

写了10年的Javascript也未必全了解的连续赋值运算
四:解惑

这篇写完,或许部分人看完还是晕晕的。因为里面的文字描述实在是绕口。最初我在理解这个连等赋值语句时

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

认为引擎会限制a.x的重写(a被重写后),实际却不是这样的。指向的对象已经不同了。引擎也没有限制a.x={n:2}的重写。
谢谢所有参与讨论的人:蔡蔡、呆呆、儒儒。这个问题最早是蔡蔡提出的。儒儒在 菜鸟灰呀灰 群里每次的讨论都那么投入,认真,哪怕是别人提出的话题。

五:结束

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

function fun(){ 
var a = b = 5; 
} 
fun(); 
alert(typeof a); // --> undefined 
alert(typeof b); // --> number
Javascript 相关文章推荐
基于jquery的超简单上下翻
Apr 20 Javascript
javascript 实现 秒杀,团购 倒计时展示的记录 分享
Jul 12 Javascript
js中call与apply的用法小结
Dec 28 Javascript
详解JS正则replace的使用方法
Mar 06 Javascript
jQuery实现可展开折叠的导航效果示例
Sep 12 Javascript
JS变量及其作用域
Mar 29 Javascript
JS仿QQ好友列表展开、收缩功能(第二篇)
Jul 07 Javascript
JavaScript实现换肤功能
Sep 15 Javascript
JQuery模拟实现网页中自定义鼠标右键菜单功能
Nov 14 jQuery
解决Vue 刷新页面导航显示高亮位置不对问题
Dec 25 Javascript
vue组件实现移动端九宫格转盘抽奖
Oct 16 Javascript
解决vue使用vant轮播组件swipe + flex时文字抖动问题
Jan 07 Vue.js
js 实现图片预加载(js操作 Image对象属性complete ,事件onload 异步加载图片)
Mar 25 #Javascript
基于jquery的3d效果实现代码
Mar 23 #Javascript
jquery 操作表格实现代码(多种操作打包)
Mar 20 #Javascript
jQuery实现的Email中的收件人效果(按del键删除)
Mar 20 #Javascript
jquery图片上下tab切换效果
Mar 18 #Javascript
javascript一些实用技巧小结
Mar 18 #Javascript
jquery获取下拉列表的值为null的解决方法
Mar 18 #Javascript
You might like
PHP中的cookie不用刷新就生效的方法
2012/02/04 PHP
PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
2016/09/11 PHP
php7 list()、session及其他模块的修改实例分析
2020/05/25 PHP
Javascript实现的鼠标经过时播放声音
2010/05/18 Javascript
javascript:history.go()和History.back()的区别及应用
2012/11/25 Javascript
使用JavaScript 实现各种跨域的方法
2013/05/08 Javascript
基于Unit PNG Fix.js有时候在ie6下不正常的解决办法
2013/06/26 Javascript
jQuery学习之prop和attr的区别示例介绍
2013/11/15 Javascript
jquery获取复选框被选中的值
2014/04/10 Javascript
javascript单引号和双引号的区别和处理
2014/05/14 Javascript
javascript实现密码验证
2015/11/10 Javascript
如何在Angular.JS中接收并下载PDF
2016/11/26 Javascript
Bootstrap标签页(Tab)插件使用方法
2017/03/21 Javascript
Node.js使用cookie保持登录的方法
2018/05/11 Javascript
对Vue.js之事件的绑定(v-on: 或者 @ )详解
2018/09/15 Javascript
JavaScript禁用右键单击优缺点分析
2019/01/20 Javascript
微信小程序 腾讯地图SDK 获取当前地址实现解析
2019/08/12 Javascript
javascript实现动态时钟的启动和停止
2020/07/29 Javascript
使用JavaScript获取扫码枪扫描得到的条形码的思路代码详解
2020/06/10 Javascript
[01:15:15]VG VS EG Supermajor小组赛B组胜者组第一轮 BO3第二场 6.2
2018/06/03 DOTA
Python深入学习之上下文管理器
2014/08/31 Python
Python多进程并发(multiprocessing)用法实例详解
2015/06/02 Python
通过Python爬虫代理IP快速增加博客阅读量
2016/12/14 Python
Python查询IP地址归属完整代码
2017/06/21 Python
让Python更加充分的使用Sqlite3
2017/12/11 Python
Python模拟简单电梯调度算法示例
2018/08/20 Python
使用numba对Python运算加速的方法
2018/10/15 Python
Python Gitlab Api 使用方法
2019/08/28 Python
对django layer弹窗组件的使用详解
2019/08/31 Python
如何基于python操作excel并获取内容
2019/12/24 Python
python-sys.stdout作为默认函数参数的实现
2020/02/21 Python
连锁经营管理专业大学生求职信
2013/10/30 职场文书
岗位廉洁从业承诺书
2014/03/28 职场文书
2014年售后服务工作总结
2014/11/18 职场文书
2015年数学教师工作总结
2015/05/20 职场文书
Python作用域和名称空间的详细介绍
2022/04/13 Python