简体   繁体   English

Javascript中的事件处理程序范围

[英]Event handler scope in Javascript

This is probably an easy question but I can't figure out the best answer for it. 这可能是一个简单的问题,但我无法找到最佳答案。

I have 10 <div> elements on screen. 我在屏幕上有10个<div>元素。 Each of them has a click() event listener: 他们每个人都有一个click()事件监听器:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
    <div id="element0">Click me! (0)</div>
    <div id="element1">Click me! (1)</div>
    <div id="element2">Click me! (2)</div>
    <div id="element3">Click me! (3)</div>
    <div id="element4">Click me! (4)</div>
    <div id="element5">Click me! (5)</div>
    <div id="element6">Click me! (6)</div>
    <div id="element7">Click me! (7)</div>
    <div id="element8">Click me! (8)</div>
    <div id="element9">Click me! (9)</div>
    <script type="text/javascript">
    for ( var i = 0; i < 10; i++ ) {
        var element = document.getElementById( "element" + i );
        element.onclick = function () {
            alert( "Element " + i );
        }
    }
    </script>
</body>
</html>

But every time I click on an element it says "Element 10"! 但每次我点击一个元素,它就会显示“元素10”! It seems all those event handlers are using the same value for i . 似乎所有这些事件处理程序都为i使用相同的值。

I want it to show "Element N" where N is the number of the current element. 我希望它显示“元素N”,其中N是当前元素的编号。 I don't want to extract N from the element id. 我不想从元素id中提取N. Neither I want to store it using data() method of jQuery. 我不想使用jQuery的data()方法存储它。 I believe there must be a much simpler solution to this problem, but I can't find it. 我相信这个问题必须有一个更简单的解决方案,但我找不到它。 Anyone? 任何人?

You only have one variable i in an outer scope shared by all your click handlers. 您在所有点击处理程序共享的外部作用域中只有一个变量i You need to create a local variable i for each closure. 您需要为每个闭包创建一个局部变量i This will work: 这将有效:

for ( var i = 0; i < 10; i++ ) {
    var element = document.getElementById( "element" + i );
    element.onclick = (function(i){
        // returns a new function to be used as an onclick handler
        return function () {
            alert( "Element " + i );
        }
    })(i); // Pass in the value of the outer scope i
}

Check "The Infamous Loop" problem in this article (and read the whole artice) for more information :) 检查“臭名昭著的循环”的问题这篇文章 (和阅读整条每页)了解更多信息:)

So your problem is the nature of doing async code inside of loops as the other post said. 所以你的问题就是在循环中做异步代码的本质,就像其他帖子所说的那样。 In your case though there's altogether a better way to solve this problem and that's using event delegation. 在你的情况下,尽管有一个更好的方法来解决这个问题,并使用事件委托。

document.body.onclick = function(e) {
  if (e.target.tagName.toLowerCase() === "div") {
    alert( "Element " + e.target.id );
  }
}

If you had jQuery you could do this: 如果你有jQuery,你可以这样做:

$(document.body).on("click", "div", function() {
  alert($(this).attr("id"));
});

For more info check out this article: http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/ 有关更多信息,请查看此文章: http//www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/

Obviously jQuery and other libs handle this stuff automatically as well. 显然jQuery和其他libs也会自动处理这些东西。

You could grab the number from the element's id attribute: 你可以从元素的id属性中获取数字:

for ( var i = 0; i < 10; i++ ) {
    var element = document.getElementById( "element" + i );
    element.onclick = function () {

        var i = this.id.substr(7);
        alert( "Element " + i );
    }
}​

JsFiddle here . JsFiddle在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM