寫了10年Javascript未必全了解的連續(xù)賦值運(yùn)算

2018-06-16 18:32 更新

一、引子

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

看 jQuery 源碼 時發(fā)現(xiàn)的這種寫法。 以上第二句 a.x = a = {n:2} 是一個連續(xù)賦值表達(dá)式。 這個連續(xù)賦值表達(dá)式在引擎內(nèi)部究竟發(fā)生了什么?是如何解釋的?

二、猜想

猜想1:從左到右賦值,a.x 先賦值為 {n:2},但隨后 a 賦值為 {n:2}, 即 a 被重寫了,值為 {n:2},新的 a 沒有 x 屬性,因此為 undefined。

步驟如下

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

這種解釋得出的結(jié)果與實(shí)際運(yùn)行結(jié)果一致,貌似是對的。

注意「猜想1」中 a.x 被賦值過。

猜想2:從右到左賦值,a 先賦值為 {n:2},a.x 發(fā)現(xiàn) a 被重寫后(之前 a 是 {a:1}), a.x = {n:2} 引擎限制 a.x 賦值,忽略了。

步驟如下:

a = {n:2};
a.x 未被賦值{n:2}

等價于 a.x = (a = {n:2}),即執(zhí)行了第一步,這樣也能解釋 a.xundefined 了。

注意「猜想2」中 a.x 壓根沒被賦值過。

三、證明

上面兩種猜想相信多數(shù)人都有,群里討論呆呆認(rèn)為是「猜想1」, 我認(rèn)為是「猜想2」。其實(shí)都錯了。 我忽略了引用的關(guān)系。

如下,加一個變量 b,指向 a。

var a = {n:1};  
var b = a; // 持有a,以回查  
a.x = a = {n:2};  
alert(a.x);// --> undefined  
alert(b.x);// --> [object Object]  

發(fā)現(xiàn) a.x 仍然是 undefined,神奇的是 b.x 并未被賦值過(比如:b.x={n:2}),卻變成了 [object Object]。 b 是指向 a({n:1}) 的,只有 a.x = {n:2} 執(zhí)行了才說明b是有x屬性的。 實(shí)際執(zhí)行過程:從右到左,a 先被賦值為 {n:2},隨后 a.x 被賦值 {n:2}。

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

等價于

a.x = (a = {n:2});

與猜想2的區(qū)別在于 a.x 被賦值了,猜想2中并未賦值。 最重要的區(qū)別,第一步 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}。

              a.x  =  a  = {n:2}
              │      │
      {n:1}<──┘      └─>{n:2}

四:解惑

這篇寫完,或許部分人看完還是暈暈的。 因?yàn)槔锩娴奈淖置枋鰧?shí)在是繞口。

最初我在理解這個連等賦值語句時

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

認(rèn)為引擎會限制 a.x 的重寫(a 被重寫后),實(shí)際卻不是這樣的。 指向的對象已經(jīng)不同了。引擎也沒有限制 a.x={n:2} 的重寫。

五:結(jié)束

呵,以另一個連續(xù)賦值題結(jié)束。 fun 執(zhí)行后,這里的 變量 b 溢出到 fun 外成為了全局變量。

想到了嗎?

function fun(){  
    var a = b = 5;  
}  
fun();  
alert(typeof a); // --> undefined  
alert(typeof b); // --> number  

原文:http://justjavac.com/javascript/2012/04/05/javascript-continuous-assignment-operator.html

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號