流動

2015-09-22 45 views
1

誰能給我解釋一下下面的代碼和JavaScript的行爲流動

for(var i = 0; i < 5; i++) 
{ 
    setTimeout(function(){ 
    document.write('Iteration ' + i + ' <br>'); 
    },1000); 
} 

document.write('DONE!'); 

爲什麼它打印「DONE!」第一? 不應該打印循環的所有值,然後打印'完成!'?

+0

'DONE!在for循環完成後正在打印。 – Rayon

+0

[WindowTimers.setTimeout()](https://developer.mozilla.org/zh-CN/docs/Web/API/WindowTimers/setTimeout) – Liam

+1

流程爲你先設置了5個超時函數,然後打印完成 - 按順序完成。這些函數在間隔後執行,這就是爲什麼先打印完成,但程序的流程是第一個操作是設置5個超時回調。 – Mjh

回答

5

它爲什麼打印'完成!'第一?它不應該打印循環的所有值,然後打印'完成!'?

不,你明確地告訴它不要;相反,您剛剛創建了五個函數,並且五次調用setTimeout以使它們能夠在瀏覽器中稍後調用。

此代碼:

setTimeout(function(){ 
document.write('Iteration ' + i + ' <br>'); 
},1000); 

調用函數setTimeout,傳遞你看到的功能。那個功能是當時調用的而不是。它剛剛創建。 setTimeout將其稱爲,因爲它的工作。 (並且當它,它會吹走文件,因爲頁面的主解析後調用document.write完成隱含確實document.open,它消滅了之前的文件。)

因此,這裏是與該代碼會發生什麼:

  1. 變量i已創建。
  2. 它設置爲0
  3. 創建了一個函數。
  4. setTimeout與傳入的函數對象的引用一起被調用,以及值1000
  5. i遞增。
  6. 步驟2至5重複1,2,34i的值。
  7. document.write被調用值'DONE!'
  8. 約一秒鐘後,瀏覽器調用循環中創建的第一個函數。
  9. 該函數調用document.write,隱含地做一個document.open,它吹走了現有的文檔並用Iteration 5 <br>(是的,真的是5)代替它。
  10. 運行循環中創建的第二個函數,再次輸出消息。
  11. 其餘三個函數被調用,再添加三次消息。

的原因,我們看到Iteration 5五次,而不是Iteration 0,然後Iteration 1等,是這些功能有一個持久的參考變量i,而不是它的價值時,他們創建的,所以他們都稍後再閱讀它的價值,就像它們跑步的時候一樣。

+1

請參考此線程並檢查答案2:http://stackoverflow.com/questions/16523870/is-javascript-synchronousblocking-or-asynchronousnonblocking-by-default – ProblemSolver

+0

@ProblemSolver:不知道你想說什麼,但請注意,並非所有人都能以相同的順序看到答案。如果您想引用特定的答案,請使用它下面的「分享」鏈接來獲取指向該特定答案的鏈接。但是我沒有看到上面沒有涉及的任何內容。 –

0

正常情況下的Javascript是Synchronous逐行執行,但通過代碼更改,您可以在某個時間作爲異步,但實際上並不會在單獨的線程上執行。

好吧,如果你要打印Done的文件撰寫完成後立即

length = 0; 
for(var i = 0; i < 5; i++) 
{ 
    setTimeout(function(index){ 
    console.log('Iteration ' + index + ' <br>'); 
    length++; 
    callback(); 
    }(i),1000); 
} 

function callback(){ 
if(length == 5) 
    console.log('DONE!'); 
} 

我們在這裏做什麼是我們增加計數器,並嘗試以後每次調用回調函數的遞增,當計數器達到5意味着所有5個功能被稱爲,然後我們能夠打印Done

作爲一個側面和重要的提示,你試圖打印0,1,2,3,4,但實際上當你運行你的代碼時,它會給你5,5,5,5,因爲你寫ii在打印達到5的時候,這就是爲什麼它會離開for循環,但是您注意到我添加的代碼,我將i作爲參數傳遞給該函數,以便它可以爲我們保存值並且當的時間來執行funtion將會寫入0,1,2,3,4