2017-07-10 44 views
1

我想了解javascript引擎如何以及何時將值傳遞給回調函數,我嘗試過調試並在線查找,但我無法找到確切答案,請考慮以下示例:如何將值傳遞給javascript中的回調

for(var i = 0; i < 4; i++) { 
    console.log("outside callback " + i + " "); 

    setTimeout(function test(){ 
     console.log("inside callback " + i + " "); 
    },100); 
} 

此打印輸出如下

外回調0

外回調1

外回調2

外回調3

內回調4

內回調4

內回調4

內回調4

如果我只是改變我使用變量的聲明讓關鍵字如下:

for(let i = 0; i < 4; i++) { 
    console.log("outside callback " + i + " "); 

    setTimeout(function test(){ 
     console.log("inside callback " + i + " "); 
    },100); 
} 

它導致下面的輸出:

外回調0

外回調1

外回調2

外回調3

內部回調0

內部回調1

內部回調2

內部回調3

當在Chrome調試這一點,它示出了我在第一個例子中作爲封閉範圍爲測試功能和第二個例子中的塊範圍。

+1

變量作用域與「_when javascript引擎將值傳遞給回調函數_」有什麼關係? – Teemu

回答

2

這涉及到一個經常被問到的問題有關JavaScript closure inside loops – simple practical example,其中將詳細介紹爲什麼在一個循環內部創建回調函數,變量使用var有當循環結束他們到達的價值觀聲明:雖然他們可能都舉行不同的值當回調被建立時,當執行回調時,異步,一段時間後,循環已經很長時間完成了,並且在循環完成時將變量保留在閉包內。

從ECMAScript版本6開始,使用let聲明的變量是塊範圍的,不能在定義它們的代碼塊之外訪問。 另外for循環控制語句中定義的變量會受到特殊處理。

  1. 它們的範圍是for循環體的範圍,而不是包含for循環的代碼塊。
  2. 爲循環的每次迭代創建一個新的let變量綁定。這意味着每個迭代都可以擁有自己的一組變量值,保存在迭代創建的詞彙環境記錄中,可以在閉包中使用該記錄,並可以通過循環內定義的回調函數訪問。

  3. 循環計數器的每個詞彙環境記錄值的目的是使使用多個環境記錄很大程度上是透明的:

    for(part1; part2; part3) { 
        // loop body code 
    } 
    
    • 在第一次迭代中,for語句中let定義的變量有在執行part1part2之後它們將具有的值。
    • 在隨後的迭代中,它們具有通過在當前迭代的環境記錄中初始化它們的值並在先前迭代結束時對其進行初始化,然後在上述for語句中執行part3part2確定的值。
    • 回撥for循環體訪問內聲明的函數在其回調成立,不包括評估for聲明part3副作用的迭代年底舉行let定義的變量的值。
1

這實際上是因爲使用let和var聲明瞭varaibles的範圍,不僅僅是javascript的閉包屬性。

+0

請問你能解釋一下這裏究竟發生了什麼 –

+0

我希望這個[post](https://stackoverflow.com/questions/4535994/why-are-closures-better-than-global-variables-for-preserving-變量)非常清楚地解釋了使用全局名稱空間的問題。 – Charles