摘要:有這樣一個(gè)熱門問(wèn)題其實(shí)這個(gè)問(wèn)題很好理解,關(guān)鍵要弄清下面兩個(gè)知識(shí)點(diǎn)引擎對(duì)賦值表達(dá)式的處理過(guò)程賦值運(yùn)算的右結(jié)合性一賦值表達(dá)式形如的表達(dá)式稱為賦值表達(dá)式。賦值表達(dá)式是右結(jié)合的。
有這樣一個(gè)熱門問(wèn)題:
var a = {n: 1}; var b = a; a.x = a = {n: 2}; alert(a.x); // --> undefined alert(b.x); // --> {n: 2}
其實(shí)這個(gè)問(wèn)題很好理解,關(guān)鍵要弄清下面兩個(gè)知識(shí)點(diǎn):
JS引擎對(duì)賦值表達(dá)式的處理過(guò)程
賦值運(yùn)算的右結(jié)合性
一. 賦值表達(dá)式形如
A = B
的表達(dá)式稱為賦值表達(dá)式。其中A和B又分別可以是表達(dá)式。B可以是任意表達(dá)式,但是A必須是一個(gè)左值。
所謂左值,就是可以被賦值的表達(dá)式,在ES規(guī)范中是用內(nèi)部類型引用(Reference)描述的。例如:
表達(dá)式foo.bar可以作為一個(gè)左值,表示對(duì)foo這個(gè)對(duì)象中bar這個(gè)名稱的引用;
變量email可以作為一個(gè)左值,表示對(duì)當(dāng)前執(zhí)行環(huán)境中的環(huán)境記錄項(xiàng)envRec中email這個(gè)名稱的引用;
同樣地,函數(shù)名func可以做左值,然而函數(shù)調(diào)用表達(dá)式func(a, b)不可以。
那么JS引擎是怎樣計(jì)算一般的賦值表達(dá)式 A = B的呢?簡(jiǎn)單地說(shuō),按如下步驟:
計(jì)算表達(dá)式A,得到一個(gè)引用refA;
計(jì)算表達(dá)式B,得到一個(gè)值valueB;
將valueB賦給refA指向的名稱綁定;
返回valueB。
二. 結(jié)合性所謂結(jié)合性,是指表達(dá)式中同一個(gè)運(yùn)算符出現(xiàn)多次時(shí),是左邊的優(yōu)先計(jì)算還是右邊的優(yōu)先計(jì)算。
賦值表達(dá)式是右結(jié)合的。這意味著:
A1 = A2 = A3 = A4
等價(jià)于
A1 = (A2 = (A3 = A4))三. 連等的解析
好了,有了上面兩部分的知識(shí)。下面來(lái)看一下JS引擎是怎樣運(yùn)算連等賦值表達(dá)式的。
以下面的式子為例:
Exp1 = Exp2 = Exp3 = Exp4
首先根據(jù)右結(jié)合性,可以轉(zhuǎn)換成
Exp1 = (Exp2 = (Exp3 = Exp4))
然后,我們已經(jīng)知道對(duì)于單個(gè)賦值運(yùn)算,JS引擎總是先計(jì)算左邊的操作數(shù),再計(jì)算右邊的操作數(shù)。所以接下來(lái)的步驟就是:
計(jì)算Exp1,得到Ref1;
計(jì)算Exp2,得到Ref2;
計(jì)算Exp3,得到Ref3;
計(jì)算Exp4,得到Value4。
現(xiàn)在變成了這樣的:
Ref1 = (Ref2 = (Ref3 = Value4))
接下來(lái)的步驟是:
將Value4賦給Exp3;
將Value4賦給Exp2;
將Value4賦給Exp1;
返回表達(dá)式最終的結(jié)果Value4。
注意:這幾個(gè)步驟體現(xiàn)了右結(jié)合性。
總結(jié)一下就是:
四. 問(wèn)題的解決先從左到右解析各個(gè)引用,然后計(jì)算最右側(cè)的表達(dá)式的值,最后把值從右到左賦給各個(gè)引用。
現(xiàn)在回到文章開(kāi)頭的問(wèn)題。
首先前兩個(gè)var語(yǔ)句執(zhí)行完后,a和b都指向同一個(gè)對(duì)象{n: 1}(為方便描述,下面稱為對(duì)象N1)。然后來(lái)看
a.x = a = {n: 2};
根據(jù)前面的知識(shí),首先依次計(jì)算表達(dá)式a.x和a,得到兩個(gè)引用。其中a.x表示對(duì)象N1中的x,而a相當(dāng)于envRec.a,即當(dāng)前環(huán)境記錄項(xiàng)中的a。所以此時(shí)可以寫(xiě)出如下的形式:
[[N1]].x = [[encRec]].a = {n: 2};
其中,[[]]表示引用指向的對(duì)象。
接下來(lái),將{n: 2}賦值給[[encRec]].a,即將{n: 2}綁定到當(dāng)前上下文中的名稱a。
接下來(lái),將同一個(gè){n: 2}賦值給[[N1]].x,即將{n: 2}綁定到N1中的名稱x。
由于b仍然指向N1,所以此時(shí)有
b <=> N1 <=> {n: 1, x: {n: 2}}
而a被重新賦值了,所以
a <=> {n: 2}
并且
a === b.x五. 最后的最后
如果你明白了上面所有的內(nèi)容,應(yīng)該會(huì)明白a.x = a = {n:2};與b.x = a = {n:2};是完全等價(jià)的。因?yàn)樵诮馕?b>a.x或b.x的那個(gè)時(shí)間點(diǎn)。a和b這兩個(gè)名稱指向同一個(gè)對(duì)象,就像C++中同一個(gè)對(duì)象可以有多個(gè)引用一樣。而在這個(gè)時(shí)間點(diǎn)之后,不論是a.x還是b.x,其實(shí)早就不存在了,它已經(jīng)變成了那個(gè)內(nèi)存中的對(duì)象.x了。
最后用一張圖表示整個(gè)表達(dá)式的運(yùn)算過(guò)程:
六. 參考文檔11.13.1 Simple Assignment ( = )
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78389.html
摘要:引擎對(duì)堆內(nèi)存中的對(duì)象進(jìn)行分代管理新生代存活周期較短的對(duì)象,如臨時(shí)變量字符串等。內(nèi)存泄漏對(duì)于持續(xù)運(yùn)行的服務(wù)進(jìn)程,必須及時(shí)釋放不再用到的內(nèi)存。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開(kāi)始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第4天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)劃...
摘要:有三個(gè)重要組成部分和。參考小結(jié)函數(shù)中的是由調(diào)用函數(shù)的方式?jīng)Q定的。構(gòu)造函數(shù)中的當(dāng)構(gòu)造函數(shù)通過(guò)操作符來(lái)調(diào)用時(shí),表示正在創(chuàng)建的對(duì)象。情況沒(méi)有明確作用對(duì)象的情況下,通常為全局對(duì)象例如函數(shù)的回調(diào)函數(shù),它的就是全局對(duì)象。 一. this的來(lái)源 this是JavaScript的關(guān)鍵字,它最初應(yīng)該是從Java、C++等面向?qū)ο蟮恼Z(yǔ)言中借鑒來(lái)的。 比如,在Java中沒(méi)有函數(shù)只有方法,this只能用在類的...
摘要:既然是屬性,當(dāng)然可以賦值。然而這三個(gè)屬性又是不可寫(xiě)的屬性,即它們的的內(nèi)部特性為,所以賦值無(wú)效。因?yàn)閲?yán)格模式下,禁止給對(duì)象的只讀屬性賦值。雖然號(hào)稱是這種原始類型可以取的唯一值,然而輸出參考文檔 提出問(wèn)題 如下代碼: undefined = 123; null = 123; // 報(bào)錯(cuò):Uncaught Reference Error 第一條語(yǔ)句可以執(zhí)行,盡管賦值并沒(méi)有成功;第二條語(yǔ)句報(bào)錯(cuò)...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書(shū)清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書(shū)清單也要收費(fèi)。這本書(shū)便從的異步編程講起,幫助我們?cè)O(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡(jiǎn)單的頁(yè)面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書(shū)清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書(shū)清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書(shū)清單也要收費(fèi)。這本書(shū)便從的異步編程講起,幫助我們?cè)O(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡(jiǎn)單的頁(yè)面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書(shū)清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...
閱讀 2072·2021-11-12 10:36
閱讀 1949·2021-11-09 09:49
閱讀 2644·2021-11-04 16:12
閱讀 1189·2021-10-09 09:57
閱讀 3276·2019-08-29 17:24
閱讀 1945·2019-08-29 15:12
閱讀 1308·2019-08-29 14:07
閱讀 1318·2019-08-29 12:53