cnblogs标题: JS连等赋值的坑

关于JS连等赋值有个经典的笔试题:

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

咋一看, 一脸懵逼, 这都什么玩意. 我一开始也是这个想法, 不过理解之后发现, 不是题目坑,

确实自己水平还不到位. 本文先介绍理解上述笔试题需要的知识点, 然后对该笔试题详细分析.

单个赋值表达式

形如A = B的表达式被称为赋值表达式, 其中A和B又分别可以是表达式, B可以是任意表达式,

而A必须是可以被赋值的表达式. 最关键的是我们要理解JS引擎是如何解析赋值表达式的:

  1. 先计算表达式A, 得到一个引用refA;
  2. 再计算表达式B, 得到一个值valueB;
  3. 将valueB赋给refA指向的位置;
  4. return valueB;

这4个步骤最核心的是规定了, 必须先计算A, 再计算B. 我们在文末分析笔试题就会看到.

多个连等解析

A1 = A2 = A3 = A4, 知道单个赋值表达式的解析逻辑, 多个连等赋值就很容易类推. 出现

多个连等, 我们完全可以给它分解成单个等号的形式. 比如上式可以分解成下面这样:

A1 = (A2 = A3 = A4), 左边的A1看成单个赋值表达式中的A, 右边整体看成B. 继续分解,

最终得出这样A1 = (A2 = (A3 = A4)). 因此这个连等的按步骤执行如下:

  1. 依次计算A1, A2, A3, 分别得到refA1, refA2, refA3;
  2. 计算A4得到valueA4, 把valueA4赋给A3;
  3. 把(A3 = A4)这个赋值表达式的返回值, 也就是value4赋给A2;
  4. 把(A2 = (A3 = A4))这个赋值表达式的返回值, 也就是value4赋给A1;

大家不要蒙圈, 就在脑中这样想, 先计算左后计算右. 左边就单个A1, OK直接计算. 来到右

边发现没法直接计算, 那么就把右边再分成左右, 按照这种思路循环递推就行.

和学二叉树时候的思路, 简直如出一辙.

再看笔试题

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

你可能会发现, 现在貌似还是不理解上面的代码到底发生了什么, 说明对JS中引用赋值, 理解还不

够透彻.

上面总共5行代码, 按顺序编号1-5.

  1. 首先执行前2行代码, 我们脑中大致有这样的图. a --> [ {n: 1} ] <--b, 说这是图太勉强, 大家

    将就看_. 这个图中间的[]表示这是个盒子, 盒子里面装有{n: 1}这个对象,ab都指向这个

    对象.
  2. 接下来, 到了全文最关键的时刻. 按照我们前面的分析, 第3行代码先执行a.x, 这时候我们上面的

    的图已经发生变化了, 变成这样a --> [ {n: 1, x: } ] <--b, 我们的x同学已经准备好了, 等着

    别人给它赋值呢.
  3. 再接着执行a, 我们的图没发生变化.
  4. 在接着执行{n: 2}, 大家注意这可是我们全新召唤出来的盒子, 盒子里面装有数据{n: 2}. 该

    盒子和前面的{n: 1}盒子没有任何关系(到目前为止).
  5. 为了方面我们就把第一次出现的盒子叫做盒子1, 第2次出现的的字叫做盒子2. 现在我们把盒子2赋给

    a, 我们的脑中将出现2个图. 图1[ {n: 1, x: } ] <--b, 图2a --> [ {n: 2} ]. 也就是说

    a已经指向了盒子2, 而b仍旧指向盒子1.
  6. 我们把a = {n: 2}这个表达式的返回值{n: 2}赋给x同学, 对就是x, x一直在等着呢, 现在

    没有a什么事了. 最终我们的图变成了这样, 图1[ {n: 1, x: {n: 2} } ] <--b,

    图2a --> [ {n: 2} ].

我们上述6个步骤图的变化单门拿出来:

a --> [ {n: 1} ] <--b

a --> [ {n: 1, x: } ] <--b

[ {n: 1, x: } ] <-- b
a --> [ {n: 2} ] // 最终图
[ {n: 1, x: {n: 2} } ] <--b
a --> [ {n: 2} ]

现在让我们输出什么, 我们就能输出什么.

console.log(a.x);   // a现在指向的盒子2, 盒子2里没有x, 输出undefined
console.log(b.x.n); // 2

参考链接

https://segmentfault.com/a/1190000004224719#articleHeader0

JS连等赋值的坑的更多相关文章

  1. (网页)Angular.js 中 copy 赋值与 = 赋值 区别

    转自st.gg Angular.js 中 copy 赋值与 = 赋值 区别 为什么用 $scope.user = $scope.master; $scope.master 会跟着 $scope.use ...

  2. 关于JS变量提升的一些坑

    function log(str) { // 本篇文章所有的打印都将调用此方法 console.log(str); } 函数声明和变量声明总是会被解释器悄悄地被“提升”到方法体的最顶部 变量声明.命名 ...

  3. 蛮考验基础的JS笔试题(有坑小心!)

    1.  考察this var length = 10 function fn(){ alert(this.length) } var obj = { length: 5, method: functi ...

  4. JS 的引用赋值与传值赋值

    这个问题说大不大说小不小,如果你有幸踩了这个坑,一定会找这篇文章,哈哈~ 现说一下JS数字的类型:基本类型和引用类型 先看下下面两个栗子: var a = 30; var b = a; a = 20; ...

  5. js连等赋值

    引用:http://www.iteye.com/topic/785445 https://segmentfault.com/q/1010000002637728 这是一个问题 var a = {n:1 ...

  6. js的this上下文的坑

    很明显,this这个坑,在多层嵌套的时候还是一样被废,不管是call, apply还是bind. 例如: var fun = function() { this.name = 'test'; var ...

  7. 用js刷题的一些坑

    leecode可以用js刷题了,我大js越来越被认可了是吧.但是刷题中会因为忽略js的一些特性掉入坑里.我这里总结一下我掉过的坑. 坑1:js中数组对象是引用对象 js中除了object还有数组对象也 ...

  8. Js的引用赋值与传值赋值

    要说js的赋值方式时首先要说明js的数值类型:基本类型和引用类型. 1.基本类型 基本的数据类型有:undefined,boolean,number,string,null. 基本类型存放在栈区,访问 ...

  9. js关键字与保留字的坑。

    在写一个算法,迷宫出口的算法,作为一个有追求的前端,首先在解决算法的问题之前要把迷宫的图做的漂漂亮亮的才对得住自己的审美,所以我花了一个钟的时间去写这个地图. 不过这次我们说的并不是迷宫的解法,也不是 ...

随机推荐

  1. Google Analytics Advanced Configuration - Google Analytics 高级配置

    该文档提供了Android SDK v3的部分元素的高级配置说明. Overview - 概述 Android Google Analytics SDK提供了Tracker类,应用可以用它给Googl ...

  2. :(23, 7) in class Queen, multiple overloaded alternatives of constructor Queen define default arguments. class Queen private(val name:String,prop:Array[String],private[scala02] val age:Int = 18){

  3. STM32F10x_硬件I2C读写EEPROM(标准外设库版本)

    Ⅰ.写在前面 上一篇文章是“STM32F10x_模拟I2C读写EEPROM”,讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程. 上一篇文章主要内容:I2C协议.模 ...

  4. Android 启动界面的实现(转载)

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...

  5. chckbox多选

    1.HTML结构 <input type="checkbox" name="test" value="1"/><span& ...

  6. jquery mobile demo

    <!DOCTYPE html> <html> <head> <title>jQuery Mobile Demo</title> <me ...

  7. 第二百二十五节,jQuery EasyUI,PropertyGird(属性表格)组件

    jQuery EasyUI,PropertyGird(属性表格)组件 学习要点: 1.加载方式 2.属性列表 3.方法列表 本节课重点了解 EasyUI 中 PropertyGird(属性表格)组件的 ...

  8. 用HTML创建表格

    本章目标:了解掌握表格的基本结构<table><tr><th><td> 掌握跨行.跨列属性colspan rowspan 掌握表格相关修饰属性borde ...

  9. 从客户端检测到有潜在危险的Request.Form 值”错误提示

    http://www.cnblogs.com/UouHt/archive/2008/10/30/1322697.html asp.net开发中,经常遇到“从客户端检测到有潜在危险的Request.Fo ...

  10. Telnet发送邮件之聊以自慰

    北京的冬天,闲着无聊,得做点什么暖暖脑袋,用windows系统自带工具telnet玩了把邮件发送 准备工作: 1.打开windows系统telnet客户端功能 2.准备两个邮箱帐号(xxx@163.c ...