在js中,函數(shù)存在一個(gè)隱式屬性[[Scopes]],這個(gè)屬性是用來(lái)保存當(dāng)前函數(shù)的執(zhí)行上下文環(huán)境悔叽,也是VO的一個(gè)集合莱衩,由于在數(shù)據(jù)結(jié)構(gòu)上是鏈?zhǔn)降模虼艘脖环Q作是函數(shù)作用域鏈娇澎,我們可以把它理解為一個(gè)數(shù)組笨蚁,可以理解為一系列的AO對(duì)象所組成的一個(gè)鏈?zhǔn)浇Y(jié)構(gòu)。
對(duì)于 AO 不清楚的同學(xué)趟庄,我也整理了一篇簡(jiǎn)易的文檔括细,可以點(diǎn)擊AO 或者移步主頁(yè)查看。
function foo(){}
console.dir(foo)
- 當(dāng)函數(shù)被調(diào)用后
function foo(){
console.dir(foo)
}
foo()
通過(guò)給 console.dir(foo)這一行代碼打斷點(diǎn)就可以清晰的看到 scope 下面分別有 local 和 global
因此戚啥,我們可以得出一個(gè)結(jié)論:[[scopes]]屬性在函數(shù)聲明時(shí)產(chǎn)生奋单,在函數(shù)調(diào)用時(shí)更新,在函數(shù)調(diào)用時(shí)猫十,將該函數(shù)的AO對(duì)象壓入到[[scopes]]中览濒。
作用域鏈的作用
作用域鏈的作用是保證執(zhí)行環(huán)境里面的有權(quán)訪問(wèn)的變量和函數(shù)是有序的,作用域的變量只能向上訪問(wèn)拖云,變量對(duì)象訪問(wèn)到 window 對(duì)象即被終止贷笛,作用域鏈向下訪問(wèn)是不被允許的。
最直觀的變現(xiàn)就是:
函數(shù)內(nèi)部可以訪問(wèn)函數(shù)外部聲明的變量
var a = 4
function foo(){
console.log(a)
}
foo() // 4
函數(shù)外部不可以訪問(wèn)函數(shù)內(nèi)部聲明的變量
function foo(){
var a = 4
}
foo()
console.log(a) // 報(bào)錯(cuò) a is not defined
畫出下面代碼執(zhí)行的作用域鏈
var global
function a(){
var aa = 123
function b(){
var bb = 345
}
b()
}
a()
-
第一步 a 定義
a 定義 -
第二步 a 執(zhí)行
a 執(zhí)行 -
第三步 b 定義
沒(méi)有 a 執(zhí)行就不會(huì)有 b 定義宙项,所以 b定義 和 a執(zhí)行 是一樣的
b 定義 -
第四步 b 執(zhí)行
b 執(zhí)行