理解JS的執(zhí)行環(huán)境

執(zhí)行環(huán)境(Execution context,EC)或執(zhí)行上下文,是JS中一個(gè)極為重要的概念

EC的組成

當(dāng)JavaScript代碼執(zhí)行的時(shí)候,會(huì)進(jìn)入不同的執(zhí)行上下文,這些執(zhí)行上下文會(huì)構(gòu)成了一個(gè)執(zhí)行上下文棧(Execution context stack,ECS)。

EC的組成

  • 變量對(duì)象(Variable object,VO): 變量對(duì)象即包含變量的對(duì)象,除了我們無(wú)法訪(fǎng)問(wèn)它外,和普通對(duì)象沒(méi)什么區(qū)別。
  • [[Scope]]屬性:作用域即變量對(duì)象,作用域鏈?zhǔn)且粋€(gè)由變量對(duì)象組成的帶頭結(jié)點(diǎn)的單向鏈表,其主要作用就是用來(lái)進(jìn)行變量查找。而[[Scope]]屬性是一個(gè)指向這個(gè)鏈表頭節(jié)點(diǎn)的指針。
  • this: 指向一個(gè)環(huán)境對(duì)象,注意是一個(gè)對(duì)象,而且是一個(gè)普通對(duì)象,而不是一個(gè)執(zhí)行環(huán)境。

產(chǎn)生EC的兩個(gè)階段

當(dāng)一段JS代碼執(zhí)行的時(shí)候,JS解釋器會(huì)通過(guò)兩個(gè)階段去產(chǎn)生一個(gè)EC

  1. 創(chuàng)建階段(當(dāng)函數(shù)被調(diào)用,但是開(kāi)始執(zhí)行函數(shù)內(nèi)部代碼之前)
  2. 創(chuàng)建變量對(duì)象VO
  3. 設(shè)置[[Scope]]屬性的值
  4. 設(shè)置this的值
  5. 激活/代碼執(zhí)行階段
    初始化變量對(duì)象,即設(shè)置變量的值、函數(shù)的引用,然后解釋/執(zhí)行代碼。

創(chuàng)建變量對(duì)象VO

  1. 根據(jù)函數(shù)的參數(shù),創(chuàng)建并初始化arguments object
  2. 掃描函數(shù)內(nèi)部代碼,查找函數(shù)聲明(function declaration)
  • 對(duì)于所有找到的函數(shù)聲明,將函數(shù)名和函數(shù)引用存入VO中
  • 如果VO中已經(jīng)有同名函數(shù),那么就進(jìn)行覆蓋
//函數(shù)聲明
function f(){}
  1. 掃描函數(shù)內(nèi)部代碼,查找變量聲明(Variable declaration)
  • 對(duì)于所有找到的變量聲明,將變量名存入VO中,并初始化為undefined
  • 如果變量名跟已經(jīng)聲明的形參或函數(shù)相同,則什么也不做
//變量聲明,必須通過(guò)var關(guān)鍵字聲明
var example = 'example'

注:步驟2和3也稱(chēng)為聲明提升(declaration hoisting)

執(zhí)行環(huán)境的分類(lèi)

  • 全局執(zhí)行環(huán)境
    在瀏覽器中,其指window對(duì)象,是JS代碼開(kāi)始運(yùn)行時(shí)的默認(rèn)環(huán)境。
    全局執(zhí)行環(huán)境的變量對(duì)象始終都是作用域鏈中的最后一個(gè)對(duì)象。
  • 函數(shù)執(zhí)行環(huán)境
    當(dāng)某個(gè)函數(shù)被調(diào)用時(shí),會(huì)先創(chuàng)建一個(gè)執(zhí)行環(huán)境及相應(yīng)的作用域鏈。然后使用arguments和其他命名參數(shù)的值來(lái)初始化執(zhí)行環(huán)境的變量對(duì)象。

注:上面的分類(lèi)也說(shuō)明了JS中只有兩種作用域(作用域即變量對(duì)象):全局作用域、函數(shù)作用域,并沒(méi)有塊級(jí)作用域,更沒(méi)有對(duì)象作用域(見(jiàn)最后的例子,但是with語(yǔ)句是一個(gè)例外,其可以臨時(shí)在作用域鏈的前端增加一個(gè)普通對(duì)象)

this

見(jiàn)文章:JS中的this

參考資料

JavaScript的執(zhí)行上下文, 五星級(jí)好文
JavaScript中的this
理解JavaScript中的作用域鏈
Scope chain
JavaScript高級(jí)程序設(shè)計(jì)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容