分別寫出for循環的打印值
for(var i=0;i<5;i++){
? ?console.log(i)
}
for(var i=0;i<5;i++){
? ? (function(i){
? ? ? ? console.log(i)
? ? ? ? })(i)
}
for(var i=0;i<5;i++){
? ? (function(){
? ? ? ? console.log(i)
? ? })(i)
}
for(var i=0;i<5;i++){
? ? setTimeout(function(){
? ? ? ? console.log(i)
? ? },i)
}
//01234
//01234
//01234
//55555
當我運行出結果的時候我第一瞬間沒有反應過來,為啥最后一個的輸出是//55555
腦袋一轉從結果出發,明白了!!!
出現55555的原因是setTimeout()中的函數是異步回調的~~并且js是單線程的!
就是在執行下面這段代碼時,瀏覽器執行到setTimeout()時,會將function(){console.log(i)}扔到事件隊列中,讓他在事件隊列中等著,然后繼續for循環
當for循環結束后,將要執行事件隊列中的回調函數~
回調函數的觸發要么是事件,要么是時間。這里是setTimeout(),觸發靠的是時間,時間耗光了,回調函數也就執行了,由于在回調函數執行之前,for循環已經結束,i的值是5; console.log(i);也就輸出了5。實際代碼的執行也可以如下理解:
for(var i=0;i<5;i++){}?
setTimeout(function(){ console.log(i) },0);?
setTimeout(function(){ console.log(i) },1);
setTimeout(function(){ console.log(i) },2);
setTimeout(function(){ console.log(i) },3);
setTimeout(function(){ console.log(i) },4);
我感覺這樣對理解第四個函數的結果就應該很清楚了。
然而第二個,第三個函數,在for循環內自執行,就是在函數體本身加上()和后面加上(),如果要傳參,就向第二個()中填寫即可,想必有些初學者,對于函數傳參會有些疑問:
JavaScript函數是不介意傳遞進來多少個參數,也不在乎傳進來參數是什么數據類型。也就是說,即便你定義的函數值接受兩個參數,在調用這個函數時也未必一定要是兩個參數。可以傳遞一個、兩個、三個甚至也可以不傳參數,而解析器永遠不會care。因為JavaScript中的參數在內部是用一個數組來運行的。函數接受到的永遠是這個數組,而不關心數組中包含哪些參數(如果有參數的話)。如果這個數組中不包含任何元素,沒關系;如果包含多個元素,也沒有問題。實際上,在函數體內可以通過arguments對象來訪問這個參數數組,從而獲取傳遞給函數的每一個參數。
同時還牽扯到JavaScript中作用域的問題,簡單的理解:在當前作用域(在這里可以理解為function函數內),如果找不到 i 的值,他就會向父作用域去找,也就是這里的for循環中,所以輸出也就很明顯了。