Scope & Closures

JS 也是編譯型語(yǔ)言,并不是邊解釋邊執(zhí)行的。
編譯的時(shí)機(jī)是代碼即將執(zhí)行之前。
Hoisting

編譯時(shí) JS 會(huì)把函數(shù)和變量的聲明提升到它們所在的 scope 的頂層

a = 2;
var a;
console.log( a ); // 2

等價(jià)于下面的代碼

var a;
a = 2;
console.log( a );
console.log( a ); // undefined
var a = 2;

等價(jià)于下面的代碼

var a;
console.log( a );
a = 2;
foo();

function foo() {
    console.log( a ); // undefined
    var a = 2;
}

同理 foo 和 a 的聲明都被提升, 還是打印 undefined

Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.
有點(diǎn)只可意會(huì)不可言傳的感覺(jué)
閉包就是當(dāng)一個(gè)函數(shù)在它的詞法域之外執(zhí)行的時(shí)候,仍然可以訪(fǎng)問(wèn)它所在的詞法域(的變量和函數(shù))
function foo() {
    var a = 2;

    function bar() {
        console.log( a );
    }

    return bar;
}

var baz = foo();

baz();

foo 返回了 bar 函數(shù), foo 執(zhí)行完畢后,baz 引用了返回的函數(shù),這時(shí)再執(zhí)行 baz 仍然可以訪(fǎng)問(wèn)到變量 a。 這里 baz 是在 global 域執(zhí)行的而不是在 foo 域執(zhí)行的。


for (var i=1; i<=5; i++) {
    setTimeout( function timer(){
        console.log( i );
    }, i*1000 );
}

將打印 5 個(gè) 6,i 會(huì)被提升到 global 域,每個(gè) setTimeout 包圍的都是 global 域中的 i

解決方案就是讓每個(gè) setTimeout 都包圍自己的域中的變量

for (var i=1; i<=5; i++) {
    (function(){
        var j = i;
        setTimeout( function timer(){
            console.log( j );
        }, j*1000 );
    })();
}

每個(gè) setTimeout 都包圍在 function 形成的獨(dú)立的域中,每個(gè)域中都有自己的變量 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)容