JS循環變量超出作用範圍


看下列代碼

var li = document.querySelectorAll('li');
for(var i = 0; i<10; ++i){
li[i].oncilck=function(){
console.log(i);//無論點擊哪個li都會輸出10
}
}

爲什麼會這樣?
這是因爲,定時器和事件處理函數還有Ajax中回調函數,均屬於異步任務
異步任務並不是在主線程中立即執行,而是放到任務隊列中,所以如果將異步任務放到for循環中,且異步任務函數中使用了循環變量,當異步任務從任務隊列中取出執行後,循環早已完成,循環變量也已經超出理想值,從而造成錯誤

這時有一個問題,爲什麼循環變量在循環外也能被訪問?看這裏.

解決方法

1.使用閉包

var li = document.querySelectorAll('li');
for(var i = 0; i<10; ++i){
	(function(i){
		li[i].oncilck=function(){
		console.log(i);
	})(i)

}
}

每次執行循環時,都會將當前的i當作實參傳入立即執行函數,此時,最內層事件處理函數中的i並非爲for循環中的循環變量i,而是立即執行函數中的參數i(內層函數訪問for循環變量時,被立即執行函數的參數頂替,而事件處理函數未觸發,則立即執行函數,無法執行完,局部變量就不會註銷)

2.使用let聲明循環變量

在另一篇中寫的很詳細.

使用let關鍵字聲明的變量才具有塊級作用域,使用var聲明的變量不具備塊級作用域特性。

for(let i = 0; i<10; ++i){
}
console.log(i);//not defined

在循環中使用let關鍵字聲明循環變量,可以防止在循壞結束後,依然可以訪問

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章