先看一段代码
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
var li=document.getElementsByTagName('li');
var len=li.length;
for(var i=0;i<len;i++){
li[i].onclick=function(){
console.log(i); //此处没有变量i,因此需要向逐级向上寻找。
}
}
依次点击li会发生什么?输出结果:
怎么样惊不惊喜,刺不刺激。意料之内的已经可以sayBye了,意料之外的往下看。
为什么会发生这种情况呢,呵呵。这是因为当我们触发点击事件的时候,for循环已经执行完毕,此时i=4,因此无论我们点击那个li标签都只会打印出4,这时就已经形成了闭包。闭包是什么?简而言之就是当内部函数被保存到外部时,将会生成闭包。闭包有很多好处,但是很不巧,此时我们就遇上了不怎么好的了。怎么办呢?!
想要实现上面的功能有三种方法:一个是再加一个闭包,使用立即执行函数,将i套现,看下方代码。一个是找一个属性,将i值保存起来,看下方代码的下方代码。一个是采用事件委托,看下方代码的下方代码的下方代码。
//方法一
var li=document.getElementsByTagName('li');
var len=li.length;
for(var i=0;i<len;i++){
(function(j){
li[j].onclick=function(){
console.log(j);
}
})(i);
}
//方法二
var li=document.getElementsByTagName('li');
var len=li.length;
for(var i=0;i<len;i++){
li[i].index=i;
li[i].onclick=function(){
console.log(this.index);
}
}
//方法三
var ul=document.getElementsByTagName('ul')[0];
ul.onclick=function(e){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == "li"){
var li=this.querySelectorAll("li");
var index = Array.prototype.indexOf.call(li,target);
console.log(index);
}
}