JS-连等、赋值表达式、链式赋值 chained assignment 的一些思考

在 ECMAScript(3rd) 文档中有关于赋值表达式的解释:

The production AssignmentExpression:

LeftHandSideExpression = AssignmentExpression
is evaluated as follows:
  1. Evaluate LeftHandSideExpression.
  2. Evaluate AssignmentExpression.
  3. Call GetValue( Result( 2 ) ).
  4. Call PutValue( Result( 1 ), Result( 3 ) ).
  5. Return Result( 3 ).

小弟自己翻译以下:

  1. 左边引用
  2. 右边引用
  3. 右边计算
  4. 赋值
  5. 返回

看上去,好像跟我们从红皮书看的运算顺序不一样,链式赋值都是从右往左的啊,怎么会是左边引用先呢?

根据这个,有比较经典的以下题目,原题:

var a = { n: 1 }, b = a; // ①
a.x = a = { n: 2 };      // ②
console.log(a.x);        // undefined
console.log(b.x);        // { n: 2 }

对以上标记的语句进行分析:

  1. 声明 a 和 b ,分配新的堆 { n: 1 },a 和 b 都赋值为指向 { n: 1 } 的地址,栈中 a 和 b 是不同的,但指向同一个堆 { n: 1 }

  1. 点运算比赋值运算优先级高,所以 a.x 会先运算,栈中找到 a,指向堆 { n: 1 },找不到 a.x,所以 js 为堆内存的对象加了个新成员 x,赋予初始值 undefined。

这也是为啥引用未定义的变量会报错,而引用一个对象的不存在的属性会返回 undefined。

(右边第一个等号开始)

  1. 【左边引用】a 此时是指向 { n: 1 } 的这个堆
  2. 【右边引用】分配了新的堆内存,存放 { n: 2 }
  3. 【右边计算】{ n: 2 }
  4. 【赋值】a = { n: 2 },此时这个 a 已经由指向 (1) 那个堆,改为了 (3) 的新堆了,而此时 b 还是指向 (1) 的堆,即 a = { n: 2 },b = { n: 1 }
  5. 【返回】{ n: 2 }

(右起第二个等号开始)

  1. 【左边引用】a.x 为 undefined,注意(1) 比 (5) 先运算,所以这个 a 啊,已经引用过了,他不会再因为 (5) 改变,a 其实是 b,即指向 { n: 1 }

增强理解:变量 a 在引用一次以后,他就不再变化了——点运算 a.x 让 a 引用了。而在(5)这个 a 赋值了新堆,那么 a 指了 { n: 2 },而 b 的引用还存在,所以 { n: 1 } 没被回收,a.x 也即 b.x

  1. 【右边引用】这里就是其右边等号的返回值,即(8)的 { n: 2 }
  2. 【右边计算】{ n: 2 }
  3. 【赋值】a.x = { n: 2 },其实就是 b 的变量赋值!
  4. 【返回】{ n: 2 }

结果如下:

console.log(a) // { n: 2 }
console.log(b) // { n: 1, x: { n: 2 } }

在so网站上找到一段代码,我们可以修改一下 a 的get/set,看看 ② 到底执行的顺序是啥:

var _a;
var logging = false;
Object.defineProperty(window, 'a', {
    get: function () {
        if (logging) {
            console.log('getting a');
        }
        return _a;
    },
    set: function (v) {
        if (logging) {
            console.log('setting a');
        }
        _a = v;
    }
});

a = { n: 1 };
var b = a;

logging = true;
a.x = a = { n: 2 };
logging = false;

console.log(a);
console.log(b);

可以看控制台的输出,是先运算了 getting 再运算 setting,而且只运算了一遍。也就是说,a 只是被引用了一遍,而且还是在赋值以前,那就是 a.x。

getting a
setting a
{ n: 2 }
{ n: 1, x: { n: 2 } }

结尾:其实有几个点还是没弄清楚

  1. 右边的引用和计算到底分别干了啥?以上没分析到答案
  2. 变量未声明直接使用会报错,对象的未声明属性却不会
console.log(hah)    // Uncaught ReferenceError: hah is not defined
var o = { o: 'o' }
console.log(o.hah)  // undefined 
console.log(o)      // { o: 'o' } 这个也没看出来有给初始值呢,也许,是在引用到未声明的属性时才会分配初始值,没有引用到就不会分配,直接将原对象引用出来

参考文章
1. What's the result of this JavaScript code snippet, and why?
2. JS:连续赋值运算

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容