js之常見問題--for循環中為什么點擊總是彈出最后一個i


首先看看點擊不同li標簽時,彈出li的索引值對應的結果

HTML:

<ul>
<li>0</li>
<li>2</li>
<li>2</li>
<li>3</li>
</ul>

JS:

for(var i = 0; i < aLi.length; i++){
aLi[i].onclick = function(){
alert(i);
}
}

運行結果不盡人意,發現點擊li后都是返回4,我們分析一下代碼,

當i = 0時,aLi[0].onclick = function(){alert(i)}

當i = 1時,aLi[1].onclick = function(){alert(i)}

當i = 2時,aLi[1].onclick = function(){alert(i)}

當i = 3時,aLi[1].onclick = function(){alert(i)}

當i = 4時,不滿足條件跳出循環

在執行click的函數的時候,會有一個作用域鏈,這個作用域鏈是一個對象列表,這組對象定義了代碼作用域中的變量。( 可以詳細了解一下變量對象的內容)當我們alert(i)的時候,會去從內到外的去尋找變量i。這個時候這個函數的作用域鏈上有4個對象,這時循環已經結束了,i此時的值為4.所以點擊任何一個li,彈出的都是4,而不是我們想要的索引值。

那么問題來了,我們為了解決這個問題我們需要做的是每次給aLi[i]綁定事件的時候,將這個時候i的值保存在內部的作用域中

方法一:使用閉包的形式

for(var i= 0;i<aLi.length;i++){
(function(i){
aLi[i].onclick=function(){
alert(i)
}
})(i)
}

這里涉及到一個塊級作用域的概念。在es6出來之前,函數是作為創建塊級作用域的主要手段。這里我們通過在aLi[i].onclick外面套上一層函數,將i作為參數,然后重新分析一下結果。

i = 0時,
(function(i){
aLi[0].onclick = function(){
alert(i);
}
})(0)
i = 1時,
(function(i){
aLi[1].onclick = function(){
alert(i);
}
})(1)
(function(i){
aLi[2].onclick = function(){
alert(i);
}
})(2)
(function(i){
aLi[3].onclick = function(){
alert(i);
}
})(4)
i = 4時,不滿足條件跳出循環.

由於多了一層自執行函數的包裹,當我們點擊li時,會有三層的作用域,從內帶外分別是:click函數內部的變量對象,自執行函數的變量對象和最外層的window對象。查找到第二層的時候,找到了i,自執行函數的i等於傳入的參數值,相對應的存下了當時i的值,所以就彈出了相應的索引值

方法二:使用ES6中的新特性let來聲明變量

for(let i=0;i<aLi.length;i++){
aLi[i].onclick = function(){
alert(i)
}
}

方法三:引入jquery,使用其中的on或delegate進行事件綁定(它們都有事件代理的特性)

$("ul").on("click", "li", function(){
var index = $(this).index();
var info = $(this).html();
alert(index + "----" + info);
});

$("ul").delegate( "li", "click",function(){
var index = $(this).index(); //索引位置
var info = $(this).html();
alert(index + "----" + info);
});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM