"点击图片显示其ID"和它的陷阱

时间:2016-02-24 18:20:01

标签: javascript scope onclicklistener

标题看起来像小菜一碟,但这并不是我想要问的。我只是想不出一个更好的头衔,如果您在阅读以下内容之后有任何内容,请发表评论,我将更新标题。 使用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书时,除了上面的方法之外,还有其他方法可以做到这一点,但我现在无法找到它。我的问题是,有没有其他方法可以做到这一点?哪一个是最好的做法?

2 个答案:

答案 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)});
}

希望这有帮助。

&#13;
&#13;
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;
&#13;
&#13;