2020-11-09第4,5章 提升&閉包

第4章 提升

  • var a = 2 引擎會(huì)將這條語句分為 var aa = 2,一個(gè)是聲明變量,編譯階段的任務(wù),而第二個(gè)是賦值,執(zhí)行階段的任務(wù)。
  • 提升是指無論作用域中的聲明出現(xiàn)在什么地方,都會(huì)在編譯階段放到最前面首先進(jìn)行處理。這個(gè)過程將變量和函數(shù)移動(dòng)到給自的作用域最頂端,這個(gè)過程被稱為”提升“
  • 函數(shù)聲明首先被提升,然后才是變量
  • 函數(shù)表達(dá)式中的變量聲明會(huì)被提升,但是賦值操作不會(huì)。
  • 這段代碼輸出的是b,因?yàn)楹瘮?shù)聲明被提升了,并且被覆蓋了
foo(); // "b" 
var a = true; 
if (a) { 
  function foo() { console.log("a"); } 
} 
else { 
  function foo() { console.log("b"); } 
}

第5章 作用域閉包

閉包是前端很重要的概念,但是很少有人能分辨清楚什么是閉包,并且如何去使用閉包。很多人認(rèn)為函數(shù)里嵌套函數(shù)就是閉包,我認(rèn)為是不對(duì)的。這本書里很好的幫我理清楚了閉包到底是什么。

  • 當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時(shí),就產(chǎn)生了閉包。即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行的。
function foo() { 
    var a = 2; 
    function bar() { 
        console.log( a ); // 2 
    }
    bar(); 
}
foo(); 

按照上面的定義,這是閉包嗎?從技術(shù)上來說,函數(shù)bar具有一個(gè)涵蓋foo作用域的閉包,但是我們無法從上面代碼看得出閉包如何工作的。看下面這段代碼:

function foo() { 
    var a = 2; 
    function bar() { 
        console.log( a ); 
    } 
    return bar; 
} 
var baz = foo(); 
baz(); // 2 —— 朋友,這就是閉包的效果。

Baz返回的是bar函數(shù),bar() 顯然是調(diào)用的地方是在自己定義的詞法作用域以外的地方執(zhí)行。一般情況,foo執(zhí)行結(jié)束后,通常會(huì)期待foo()的整個(gè)內(nèi)部作用域都會(huì)被銷毀,但是因?yàn)殚]包的作用,bar()所聲明的地方位置的隱私,它擁有foo的內(nèi)部作用域的閉包,所以不會(huì)不銷毀。bar的這個(gè)引用就叫做閉包。

  • 無論何種方式的函數(shù)值傳遞,我們都可以看見閉包的作用
function foo() { 
    var a = 2; 
    function baz() { 
        console.log( a ); // 2 
    }
    bar( baz ); 
} 
function bar(fn) { 
    fn(); // 媽媽快看呀,這就是閉包! 
}
var fn; 
function foo() { 
    var a = 2; 
    function baz() { 
        console.log( a ); 
    }
    fn = baz; // 將 baz 分配給全局變量 
} 
function bar() { 
    fn(); // 媽媽快看呀,這就是閉包! 
}
foo(); 
bar(); // 2
  • setTimeout, 事件監(jiān)聽器,ajax請(qǐng)求,跨窗口通信,異步任務(wù)等,只要用到了回調(diào)函數(shù),實(shí)際上就是在使用閉包。

循環(huán)和閉包

  • 觀察這段代碼,執(zhí)行結(jié)果:回調(diào)函數(shù)會(huì)在循環(huán)結(jié)束后執(zhí)行,因?yàn)槊看窝h(huán)都會(huì)賦值上一次運(yùn)行的值,繼續(xù)運(yùn)行。
for (var i=1; i<=5; i++) { 
    setTimeout( function timer() { 
        console.log( i ); 
    }, i*1000 ); 
} 
  • 對(duì)比和上面代碼區(qū)別
for (var i=1; i<=5; i++) { 
    (function() { 
        setTimeout( function timer() { 
            console.log( i ); 
        }, i*1000 ); 
    })(); 
}

IIFE 會(huì)通過聲明并立即執(zhí)行一個(gè)函數(shù)來創(chuàng)建作用域,雖然有了獨(dú)立的作用域但是什么都沒有,需要一個(gè)變量存儲(chǔ)變量才行

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

//改進(jìn)后

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

這里才是預(yù)期的效果,一段時(shí)間后輸出循環(huán)的參數(shù)。

小結(jié): 這部分還需要再多看幾遍,有一種似懂非懂的感覺,還不能十分把握說清楚。

?著作權(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)容