JavaScript新手必看之var在for循環(huán)中的坑
一道面試題
for(var i = 0;i<5;i++){
console.log(i)
}那么以上會輸出什么呢?答案是控制臺是依次輸出0,1,2,3,4。相信大家小伙伴們都答對了。再接再厲吧,再來一道。
for(var i = 0;i<5;i++){
setTimeout(function(){
console.log(i)
})
}這次還會是同樣的結論嗎?答案是輸出5次5。這里開始有疑惑了對吧,預期輸出應該也是0,1,2,4才對,怎么會輸出的是5呢?先開個結論,這里是和作用域有關系的。
引申
為了更進一步的去理解這個問題,來一個需求吧。用一個數(shù)組去存放函數(shù),依次輸出0-4之間的數(shù)吧。
var a = []
for (var i= 0;i<2;i++){
a[i] =function(){
console.log(i)
}
}
a.forEach(_=>{
_()
})答案同樣是只能輸出5。
原因就很簡單,因為你的每一個函數(shù)都綁定的變量i,所以每次去執(zhí)行函數(shù),都會去訪問這個變量i,因為var聲明的變量,并不只局限在for循環(huán)當中,而是在全局當中生效了!而你又不是在循環(huán)當中去調用它的,而是在循環(huán)之后去調用。在循環(huán)時,i會伴隨著循環(huán)增長,此時你調用的話,前面的確實a[i]的結果是i,但a[i-1],a[i-2]...的結果也是i,因為函數(shù)調用時,內部的i指向的是全局范圍內的i。
換言之,你數(shù)組里的函數(shù)都是引用的這個全局變量i。而不是for循環(huán)里的局部變量i。
要想解決這個問題,請接著往下看。
解決思路
思路:既然var聲明的是全局的變量,那么只要函數(shù)里的變量是局部的即可。
寫法1
巧的是ES6當中的let聲明關鍵字就是這個效果。
var a = []
for (let i= 0;i<2;i++){ //這里把原來的var聲明改成了let聲明
a[i] =function(){
console.log(i)
}
}
a.forEach(_=>{
_()
})那么可能會疑問,既然這個let聲明的i是局部變量,那么每次循環(huán)都會重新創(chuàng)建1個i吧?
是的沒錯。
那么每次都重新創(chuàng)建的話,會不會i的值也會被重新初始化呢?
答案是不會,JS引擎在for循環(huán)當中會記住前一次結束時的i值,并且在下一次創(chuàng)建時將i賦值。
寫法2
var a = []
for (var i= 0;i<2;i++){
a[i] = (function(i){
return function(){
console.log(i)
})(i)
}
a.forEach(_=>{
_()
})這里的寫法就是在每次循環(huán)當中,將循環(huán)中的i(i在不斷增長),通過形參傳進去,從而誕生出局部變量i。
附:形參傳遞的過程,基本數(shù)據(jù)類型就是將值賦給形參,而引用數(shù)據(jù)類型則是將指針賦給形參。
當心
可能會有這樣想法的同學。這樣做只是定義了函數(shù),這個函數(shù)有1個形參i而已。這樣你調用它就變成了a[i](xxx)。
var a = []
for (var i= 0;i<2;i++){
a[i] = function(i){
console.log(i)
}
}
a.forEach(_=>{
_()
})想要傳遞參數(shù)只能是(fun(i){})(i),寫成立即執(zhí)行函數(shù)調用它,這樣才能去給它傳值(形參)。
var a = []
for (var i= 0;i<2;i++){
a[i] = (function(i){
console.log(i)
})(i)
}
a.forEach(_=>{
_()
})而加入括號的時候,就會被執(zhí)行了,因此我們需要套一層return。這樣才能達到我們想要的效果
想要傳遞參數(shù)只能是(fun(i){})(i),寫成立即執(zhí)行函數(shù)調用它,這樣才能去給它傳值(形參)。
而加入括號的時候,就會被執(zhí)行了,因此我們需要套一層return。這樣才能達到我們想要的效果
到此這篇關于JavaScript新手必看之var在for循環(huán)中的坑的文章就介紹到這了,更多相關var for循環(huán)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
前端存儲后端響應數(shù)據(jù)超詳細的實現(xiàn)方式和注意事項
前端通過多種方式向后端獲取數(shù)據(jù),下面這篇文章主要介紹了前端存儲后端響應數(shù)據(jù)超詳細的實現(xiàn)方式和注意事項,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-03-03
JavaScript獲取頁面中表單(form)數(shù)量的方法
這篇文章主要介紹了JavaScript獲取頁面中表單(form)數(shù)量的方法,涉及javascript操作表單document.forms數(shù)組的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-04-04

