小記·作用域|閉包|變量提升

完全是些零碎的總結(jié)↓

變量提升?

栗子:

function test(){
console.log(foo);
var foo=1;
}

對(duì)于可執(zhí)行代碼,在其執(zhí)行之初會(huì)有一個(gè)分析的過(guò)程,分析時(shí)會(huì)預(yù)處理函數(shù)的活動(dòng)對(duì)象(AO),此時(shí)AO內(nèi)部的foo初值為undefined,只有當(dāng)真正執(zhí)行到var foo時(shí),才會(huì)賦值1,由于console.log在var之前,所以打印的foo是undefined(此時(shí)AO.foo=undefined)

簡(jiǎn)而言之:變量能提升是因?yàn)榉治鲞^(guò)程中,var聲明的鍵被初始化了。

思維導(dǎo)圖?

閉包?

JS是詞法(靜態(tài))作用域,其作用域在創(chuàng)建(而不是執(zhí)行時(shí))確定,所以

let value = 1;
function foo() {
    console.log(value);
}
function bar() {
    let value = 2;
    foo();
}
bar();

結(jié)果是value=1
原因是
1.foo和bar被在全局代碼中被創(chuàng)建,此時(shí)會(huì)初始化AO,作用域鏈,this,
2.foo和bar的作用域鏈都是[自己的AO,global.AO]
3.所以打印結(jié)果是1

這里涉及的作用域鏈,其完全與函數(shù)內(nèi)部一個(gè)叫做[[Scopes]]的屬性有關(guān),不信看下例閉包

function foo() {
    let a=1
    function bar() {
      console.log(a)
    }
   return bar
}
console.dir(foo());
//打印結(jié)果↓↓
f bar()
arguments: null
caller: null
length: 0
name: "bar"
prototype: {constructor: ?}
__proto__: ? ()
[[FunctionLocation]]: VM50:3
[[Scopes]]: Scopes[2]
0: Closure (foo) {a: 1}
1: Global {window: Window, self: Window, document: document, name: "", location: Location, …}

[[Scopes]]內(nèi)包含的就是變量對(duì)象VO,函數(shù)執(zhí)行時(shí)找變量就是從Scopes的VO按序遍歷來(lái)尋找的。
根據(jù)上面的解析過(guò)程,我們也可以如法炮制
原因:
1.全局代碼下foo被創(chuàng)建,初始化AO,作用域鏈,this,此時(shí)foo的作用域鏈?zhǔn)荹foo.AO,global.AO]
2.執(zhí)行foo
3.bar被創(chuàng)建,此時(shí)bar的作用域鏈?zhǔn)荹bar.AO,foo.[[Scopes]]]==[bar.AO,foo.AO,global.AO]
4.返回bar
5.bar的scopes沒有變化,當(dāng)然被保存了呀,所以閉包

?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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