标题看起来像小菜一碟,但这并不是我想要问的。我只是想不出一个更好的头衔,如果您在阅读以下内容之后有任何内容,请发表评论,我将更新标题。
使用jQuery,执行此操作非常简单,因为click()
传递了this
参数,
$('img').click(function(){console.log($(this).attr('id')})
我试图使用vanilla javascript做这件事,并遇到了一些陷阱
imgs = document.getElementsByTagName('img');
l = imgs.length;
for (i=0;i<l;i++) {
imgs[i].addEventListener('click',function(){console.log(imgs[i].id)});
}
这不会奏效,因为每个列表工作者都会尝试console.log(imgs[l].id)
。
我找到了解决方法:
imgs = document.getElementsByTagName('img');
l = imgs.length;
listener_generator = function(id){
var s = function(){
console.log(id);
};
return s;
};
for (i=0;i<l;i++) {
imgs[i].addEventListener('click',listener_generator(imgs[i].id));
}
出于学习目的,我记得当我读一些javascript书时,除了上面的方法之外,还有其他方法可以做到这一点,但我现在无法找到它。我的问题是,有没有其他方法可以做到这一点?哪一个是最好的做法?
答案 0 :(得分:1)
这是一个典型的关闭问题,你偶然会无意中解决这个问题。
此代码存在问题:
for (i=0;i<l;i++) {
imgs[i].addEventListener('click',function(){console.log(imgs[i].id)});
}
基本上不会立即评估console.log(imgs[i].id)
,而是在触发事件监听器时评估 。这意味着你有很多引用i
的表达式,但由于它们不会执行直到事件监听器触发,它们都保持完全相同的i
值(最后一个)它在for循环结束时的值。)
要解决这个问题,你需要&#34;关闭&#34; i
的值,用于在for循环中捕获其值,而不是在事件侦听器触发时捕获。有多种方法可以做到这一点 - 我首选的方法是创建一个匿名函数,为for循环的每次迭代执行,如下所示:
for (i=0;i<l;i++) {
(function(_i){
imgs[_i].addEventListener('click',function(){console.log(imgs[_i].id)});
})(i);
}
你通过创建一个闭包基本上意外地解决了这个问题,只有你用命名函数而不是匿名函数来做,但结果是一样的。在运行时,for循环调用一个&#34;捕获&#34;在闭包中i
的值,而不是在事件监听器触发之前将其推迟。
Here is an excellent post with more detail about how closures work.
答案 1 :(得分:1)
如果您在点击事件中用img[i]
替换this
以引用当前的img,则第一个代码应该可以正常工作:
imgs = document.getElementsByTagName('img');
l = imgs.length;
for (i=0;i<l;i++) {
imgs[i].addEventListener('click',function(){console.log(imgs[i].id)});
}
希望这有帮助。
imgs = document.getElementsByTagName('img');
l = imgs.length;
for (i=0;i<l;i++) {
imgs[i].addEventListener('click',function(){alert(this.id)});
}
&#13;
<img src='http://tny.im/3Qp' id='img_1' />
<img src='http://tny.im/3Qp' id='img_2' />
<img src='http://tny.im/3Qp' id='img_3' />
<img src='http://tny.im/3Qp' id='img_4' />
&#13;