在之前寫的進(jìn)階系列里面勾怒,提到了
執(zhí)行上下文
在創(chuàng)建階段,要?jiǎng)?chuàng)建變量對象
串结、確定作用域鏈
還有確定this的指向
蒿柳,本次將重點(diǎn)講解一下作用域鏈
。
JavaScript代碼的執(zhí)行過程
在講解作用域鏈之前岳枷,首先了解一下芒填,JavaScript代碼的執(zhí)行過程,包括兩個(gè)步驟:
- 編譯階段
- JavaScript引擎執(zhí)行階段
在編譯階段主要做的是空繁,經(jīng)過編譯器的編譯殿衰,將代碼轉(zhuǎn)化為可執(zhí)行的代碼,其中就包括了作用域規(guī)則的確定
盛泡,而在之前說的執(zhí)行上下文的創(chuàng)建和執(zhí)行階段是發(fā)生在JavaScript隱引擎執(zhí)行階段闷祥,所以作用域鏈
是在執(zhí)行上下文創(chuàng)建階段才產(chǎn)生的,這時(shí)候傲诵,可能你會疑惑凯砍,作用域和作用域鏈有什么區(qū)別呢?
什么是作用域拴竹?
作用域?yàn)橐惶滓?guī)則悟衩,用來管理引擎如何在當(dāng)前作用域以及嵌套的子作用域中根據(jù)標(biāo)識符查找變量。
在JavaScript中栓拜,主要的作用域有兩種:
- 全局作用域
- 函數(shù)作用域
什么是作用域鏈座泳?
作用域鏈?zhǔn)怯僧?dāng)前執(zhí)行環(huán)境與上層環(huán)境的一系列變量對象組成,它保證了當(dāng)前執(zhí)行環(huán)境對符合訪問權(quán)限的變量和函數(shù)的有序訪問幕与。
而作用域與作用域鏈的區(qū)別主要在于:
作用域是一套規(guī)則挑势,作用域鏈?zhǔn)亲饔糜虻木唧w實(shí)現(xiàn)。
講理論可能有些空洞纽门,那么我就舉個(gè)具體的例子來說明什么是作用域鏈吧
demo01
var a = 20;
function test(){
var b = a + 20;
function innerTest(){
var c = 10;
return b + c;
}
return innerTest();
}
test();
在這個(gè)例子中薛耻,按照之前講解的
- 先創(chuàng)建執(zhí)行上下文,按照赏陵,
globalEC
—>testEC
—>innerTestEC
的順序饼齿,壓入調(diào)用棧
中,其中主要討論innerTest()
的作用域鏈蝙搔。 - 按照作用鏈的定義缕溉,可以得出
innerTest()
執(zhí)行上下的結(jié)構(gòu),如下
innerTestEC = {
VO:{ c:10},
scopeChain:[VO(innerTest),VO(test),VO(global)],
this:{...}
}
可以看出吃型,innerTest()
的作用域鏈就是由當(dāng)前的執(zhí)行環(huán)境與上層的執(zhí)行環(huán)境中的一系列變量對象組成证鸥,所以innerTest()
就能訪問到上層執(zhí)行上下文中,變量對象中的屬性和方法,這就是作用域鏈枉层。
- 看一下
innerTest()
的作用域鏈圖泉褐,如下: