【前端工程師手冊】JavaScript作用域拾遺

昨天總結了一些作用域的學問【前端工程師手冊】JavaScript之作用域,然則宣布完發明忘記了一些東西,本日拾個遺。
昨天說到了JavaScript中沒有塊級作用域,其實在es6中是有的。

es6中的塊級作用域

先舉個栗子:

var foo = true;
if (foo) {
    let bar = foo * 2;
    bar = something( bar ); 
    console.log(bar);
 }
 console.log( bar );  // ReferenceError

這個是let最直觀的作用,在一對大括號中創建了塊級作用域,bar會在大括號中的代碼實行終了后燒毀。
再舉個栗子:

for(var i = 1;i <= 5;i++) {
    setTimeout(function() {
        console.log(i)
    }, i*1000)
}
// 每隔一秒打印一個6,共打印5次

如果說這段代碼的初志是距離1秒打印出1、2、3、4、5的話,結果是使人大跌眼鏡的,真正的結果是每隔1秒打印一次6,打印5次.
為何會這模樣?起首是因為閉包的緣由,閉包背面再說,現在先理解為閉包是一個函數,一個可以接見並未在它自己內部定義的變量的函數。
OK,接下來講深層次緣由。for輪迴終了以後,i=6,且此時生成了5個匿名函數 function(){ console.log(i) },因為這5個匿名函數處在同一個詞法作用域中,所以他們援用同一個i,所以當他們實行時,天然而然就會打出6。
怎樣處理?

for(let i = 1;i <= 5;i++) {
    setTimeout(function() {
        console.log(i)
    }, i*1000)
}
// 距離一秒離別打印出1、2、3、4、5

把var換成let聲明就可以了。
《你不知道的JavaScript-上卷》中解釋道:

for 輪迴頭部的 let 不僅將 i 綁定到了 for 輪迴的塊中,事實上它將其從新綁定到了輪迴的
每個迭代中,確保運用上一個輪迴迭代完畢時的值從新舉行賦值。

說白了就是再每次迭代內部,都會對 i 舉行隱形的從新賦值,且運用的是上一個迭代完畢時的值來對 i 舉行從新賦值。
差不多就是如許的:

for(let i = 1;i <= 5;i++) {
    let i = 上次迭代完畢的i
    setTimeout(function() {
        console.log(i)
    }, i*1000)
}

所以5個匿名函數援用的並非同一個i,天然就會順遂的距離一秒離別打印出1、2、3、4、5了

參考資料:
你不知道的JavaScript-上卷
let-MDN

    原文作者:亞古
    原文地址: https://segmentfault.com/a/1190000014817197
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞