(转)深入理解javascript连续赋值表达式
引入
今天逛园子的时候看到一道javascript面试题,是关于连续赋值的,正好最近读jQuery源码经常看到这种连续赋值的表达式,所以很感兴趣。
废话不多说,来看题:
var a = {n: 1}
var b = a;
a.x = a = {n: 2}
console.log(a.x);
console.log(b.x)
答案:
console.log(a.x); // undefined
console.log(b.x) //{n:2}
看到这个答案,我真是百思不得解。。。。 于是网上搜了搜,整理如下:
以下转自:http://www.iteye.com/topic/785445
1、引用(Reference)与GetValue & PutValue
“引用”是引用某个对象的一个属性(可能这个对象并没有这个属性),一个引用含“根对象”与“属性名”两个成员。
后面以“(根对象,属性名)”来表达一个引用
1. If Type(V) is not Reference, return V.
2. Call GetBase(V).
3. If Result(2) is null, throw a ReferenceError exception.
4. Call the [[Get]] method of Result(2), passing GetPropertyName(V) for the property name.
5. Return Result(4).
GetValue,即取值操作,返回的是确定的值,而不是引用。(可以理解为变量与变量的值,或指针与指针指向的对象)
1. If Type(V) is not Reference, throw a ReferenceError exception.
2. Call GetBase(V).
3. If Result(2) is null, go to step 6.
4. Call the [[Put]] method of Result(2), passing GetPropertyName(V) for the property name and W for the value.
5. Return.
6. Call the [[Put]] method for the global object, passing GetPropertyName(V) for the property name and W for the
value.
7. Return.
PutValue操作只对引用生效,在ECMAScript的描述中,修改对象的属性都是通过Refrence + PutValue进行的
(ECMAScript是为了便于表达而引入Reference这个类型,实际上JS语言中并无此类型。The internal Reference type is not a language data type. It is defined by this specification purely for expository
purposes.)
2、成员表达式(MemberExpression)解释过程
1. Evaluate MemberExpression.
53
2. Call GetValue(Result(1)).
3. Evaluate Expression.
4. Call GetValue(Result(3)).
5. Call ToObject(Result(2)).
6. Call ToString(Result(4)).
7. Return a value of type Reference whose base object is Result(5) and whose property name is Result(6).
着重看第7步:a value of type Reference
3、赋值表达式解析
1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).
这里可以看到左侧得出的是引用,右侧调用GetValue取得的是确定值。
那么开始分析a.b = a = {n:2}这个表达式,先假设{n:1}这个对象为OBJ1,{n:2}为OBJ2,全局为GLOBAL。
它的解析如下:
a.b = Expression1
Expression1为另一个赋值表达式:
a = {}
首先计算a.b = Expression1,按(3)中赋值表达式运行步骤
step1先得到引用(OBJ1, "b")
step2解析Expression1{
Expression1解析
step1得到引用(GLOBAL, "a")
step2得到一个对象OBJ2
step3取值,仍是OBJ2
step4将引用(GLOBAL, "a")赋值为step3结果
step5返回OBJ2
}
step3取值,结果同样为OBJ2
step4将(OBJ1, "b")赋值为OBJ2
step5返回OBJ2
最终结果:
OBJ1: {n:1, b:OBJ2}
OBJ2: {n:2}
a : OBJ2
PS:
我们常说赋值运算是从右至左,是指右边先结合
所以a.b = a = {n:2}解析为了a.b = ( a = {n:2}),而不会解析为(a.b = a) = {n:2}
如果理解为右边先运算就会有误解了,虽然右边先赋值成功。
----------------------------分割线---------------------------
附上ECMA262文档:ECMA262
(转)深入理解javascript连续赋值表达式的更多相关文章
- 深入理解javascript系列(4):立即调用的函数表达式
本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...
- [JS]深入理解JavaScript系列(4):立即调用的函数表达式
转自:汤姆大叔的博客 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行.在详细了解这个之前,我们来谈了解一下"自执行"这个叫法 ...
- 深入理解javascript:揭秘命名函数表达式
这是一篇转自汤姆大叔的文章:http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 前言 网上还没用发现有人对命名函数表达式进去重复深 ...
- <深入理解JavaScript>学习笔记(2)_揭秘命名函数表达式
写在前面的话 注:本文是拜读了 深入理解JavaScript 之后深有感悟,故做次笔记方便之后查看. 感觉这章的内容有点深奥....略难懂啊. 先坐下笔记,加深一下印象吧. 我主要记一下自己感觉有用的 ...
- 深入理解JavaScript系列(2):揭秘命名函数表达式
前言 网上还没用发现有人对命名函数表达式进去重复深入的讨论,正因为如此,网上出现了各种各样的误解,本文将从原理和实践两个方面来探讨JavaScript关于命名函数表达式的优缺点. 简单的说,命名函数表 ...
- 深入理解JavaScript系列(2):揭秘命名函数表达式(转)
前言 网上还没用发现有人对命名函数表达式进去重复深入的讨论,正因为如此,网上出现了各种各样的误解,本文将从原理和实践两个方面来探讨JavaScript关于命名函数表达式的优缺点. 简 单的说,命名函数 ...
- 深入理解JavaScript的闭包特性如何给循环中的对象添加事件
初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...
- 深入理解javascript原型和闭包(8)——简述【执行上下文】上
什么是“执行上下文”(也叫做“执行上下文环境”)?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时, ...
- 深入理解javascript原型和闭包(9)——简述【执行上下文】下
继续上一篇文章(http://www.cnblogs.com/wangfupeng1988/p/3986420.html)的内容. 上一篇我们讲到在全局环境下的代码段中,执行上下文环境中有如何数据: ...
随机推荐
- 基于服务(Web Service)的文件管理Winform程序实现
1. 描述 面向服务的体系结构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来.接口是采用中立的方式进行定义的,它应该独立于实现 ...
- 右键添加 CMD 命令提示符
# 右键添加 CMD 命令提示符 当然是修改注册表 - 打开注册表编辑器(按下Win+R打开运行对话框,输入regedit),找到[HKEY_CLASSES_ROOT/Folder/shell] ...
- SOAOffice和iWebOffice、NTKO的比较及其优势(转)
http://www.cnblogs.com/liping13599168/articles/1681465.html SOAOffice和iWebOffice.NTKO的比较及其优势 近年来,市场上 ...
- <<Exceptional C++>> notes
- class Complex { public: ) : real_(real), imaginary_(imaginary) { } Complex& operaor+=(const Co ...
- 集合Collection
/* * 集合的由来: * 我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储. * 而要想存储多个对象,就不能是一个基本 ...
- Oracle补习班第九天
Better to light one candle than to curse the darkness. 与其诅咒黑暗,不如点亮烛光! 1,用SQL备份数据库数据文件 sqlplus / as s ...
- List Arraylist 数组的区别
数组.List和ArrayList的区别 数组在内存中是连续存储的,所以它的索引速度是非常的快,而且赋值与修改元素也很简单,比如: ]; //赋值 s[]=]=]="c"; //修 ...
- 【webpy开发实战】webpy的cookbook 个人版
版本:webpy0.3 问题1.1 所需软件及环境配置? 解决办法 sqlite: jinja2:找不到jinja2模块时,将jinja模块文件夹加入 sys.path -> sys.path ...
- inux grep 命令 搜索含有"zynq"字符的文件
使用命令grep -rl 'zynq' /work/xilinx/u-boot-xlnx-master (有引号)-r 选项表示递归(recursive)遍历所有子目录-l 选项表示只列出文件名 /w ...
- Ubuntu12.04解决gedit中文乱码问题
Ubuntu12.04,终端中分别输入下面两条指令: gsettings set org.gnome.gedit.preferences.encodings auto-detected “['GB18 ...