写了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中的查找parents与closest方法之间的区别
Dec 02 Javascript
javascript分页代码实例分享(js分页)
Dec 13 Javascript
window.print打印指定div实例代码
Dec 13 Javascript
php常见的页面跳转方法汇总
Apr 15 Javascript
JQuery实现带排序功能的权限选择实例
May 18 Javascript
jQuery实现类似老虎机滚动抽奖效果
Aug 06 Javascript
AngularJS 限定$scope的范围实例详解
Jun 23 Javascript
JavaScript字符串检索字符的方法
Jun 23 Javascript
Vue修改项目启动端口号方法
Nov 07 Javascript
JS前端广告拦截实现原理解析
Feb 17 Javascript
解决vant框架做H5时踩过的坑(下拉刷新、上拉加载等)
Nov 11 Javascript
VUE实现吸底按钮
Mar 04 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
松下Panasonic RF-B65电路分析
2021/03/02 无线电
php+js实现百度地图多点标注的方法
2016/11/30 PHP
如何通过View::first使用Laravel Blade的动态模板详解
2017/09/21 PHP
Extjs4 Treegrid 使用心得分享(经验篇)
2013/07/01 Javascript
使用javascript创建快捷方式的简单实例
2013/08/09 Javascript
jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别
2013/12/02 Javascript
jquery任意位置浮动固定层插件用法实例
2015/05/29 Javascript
JavaScript中的Math.atan2()方法使用详解
2015/06/15 Javascript
浅谈JS中逗号运算符的用法
2016/06/12 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
2017/02/22 Javascript
JS实现禁止高频率连续点击的方法【基于ES6语法】
2017/04/25 Javascript
解决Vue.js 2.0 有时双向绑定img src属性失败的问题
2018/03/14 Javascript
Vue实现内部组件轮播切换效果的示例代码
2018/04/07 Javascript
vue 自定义提示框(Toast)组件的实现代码
2018/08/17 Javascript
微信小程序实现列表页的点赞和取消点赞功能
2018/11/02 Javascript
ES6基础之解构赋值(destructuring assignment)
2019/02/21 Javascript
react实现同页面三级跳转路由布局
2019/09/26 Javascript
解决vue初始化项目一直停在downloading template的问题
2020/11/09 Javascript
[06:40]2014DOTA2西雅图国际邀请赛 DK战队巡礼
2014/07/07 DOTA
对Python 两大环境管理神器 pyenv 和 virtualenv详解
2018/12/31 Python
Python实现EXCEL表格的排序功能示例
2019/06/25 Python
python pandas cumsum求累计次数的用法
2019/07/29 Python
Pycharm远程连接服务器并实现代码同步上传更新功能
2020/02/25 Python
python入门之井字棋小游戏
2020/03/05 Python
Tensorflow tensor 数学运算和逻辑运算方式
2020/06/30 Python
Python创建临时文件和文件夹
2020/08/05 Python
用CSS3实现背景渐变的方法
2015/07/14 HTML / CSS
摩顿布朗英国官方网上商店:奢华沐浴、身体和头发护理
2016/10/29 全球购物
Manuka Doctor美国官网:麦卢卡蜂蜜和蜂毒护肤
2016/12/25 全球购物
世界上最受欢迎的花店:1-800-Flowers.com
2020/06/01 全球购物
外贸业务员工作职责
2014/01/06 职场文书
护士毕业自我鉴定
2014/02/07 职场文书
交通志愿者活动总结
2014/06/27 职场文书
ktv好的活动方案
2014/08/17 职场文书
在Python中如何使用yield
2021/06/07 Python
Mysql排查分析慢sql之explain实战案例
2022/04/19 MySQL