变量事件

时间:2009-12-22 22:21:14

标签: javascript events variables for-loop

我收到了这段代码:

<script>window.onload = function () {
    var container, i;

    for (i = 0; i < 10; i ++) {
        container = document.createElement ("div");
            container.innerHTML = i;

            container.style.border = "1px solid black";
            container.style.padding = "10px";

            container.onclick = function () {
                alert (i);
            }

        document.body.appendChild (container);
    }
}</script>

我想知道为什么当我点击元素时我得到错误的数字:(

由于

7 个答案:

答案 0 :(得分:3)

这是匿名函数的经典范围问题。

函数中的变量i对于您添加的每个事件处理程序都是相同的 - 因此它们都会提醒相同的值。

您想为每个变量创建一个新范围:例如:

function createAlertFunction(i) {
    return function() {
        alert(i);
    }
}

//...

container.onclick = createAlertFunction(i);

答案 1 :(得分:2)

您需要为每次迭代创建自己的函数。试试这个:

container.onclick = (function(i) {
    return function() {
        alert(i);
    };
})(i);

这里外部函数(function(i) { … })用于返回值为i的新函数。调用此函数((function(i) { … })(i))时,i将传递给该函数并嵌入到返回的函数中。

答案 2 :(得分:1)

它没有显示错误的值,它在调用内部匿名函数时显示i的值。我认为当函数绑定到相应的div的onclick事件时,你希望它显示i的值。

答案 3 :(得分:1)

类似于GumboAnon的答案,虽然我个人认为它更容易阅读(仅我的意见)。

window.onload = function () {
        var container, i;

        for (i = 0; i < 10; i ++) {
            (function() {
                container = document.createElement ("div");
                container.innerHTML = i;

                container.style.border = "1px solid black";
                container.style.padding = "10px";

                container.onclick = function () {
                                        alert (i);
                                    };

                document.body.appendChild (container);
            })();
       }
}

答案 4 :(得分:0)

在这里,你试图创造一种叫做“封闭”的东西。它用变量“i”的值关闭最后一个已知的上下文。因此,要在闭包内获取正确的值,必须通过将变量值传递给内部函数的新本地作用域来创建新的上下文。关于闭包的更多信息:http://www.jibbering.com/faq/faq%5Fnotes/closures.html

答案 5 :(得分:0)

不是使用闭包创建大量几乎相同的函数,为什么不尝试这样的事情:

function containerOnClick () {
    alert(this.index);
}

window.onload = function() {
    var container, i;
    for (i = 0; i < 10; i++) {
        // -- snip --
        container.index = i;
        container.onclick = containerOnClick;
    }
};

根据onclick处理程序的大小以及总共有的​​容器数量,这可能会减少内存占用量。

答案 6 :(得分:-1)

您可以使用with

var container, i;
for (i = 0; i < 10; i ++) {
    with ({ locali: i }) {
        container = document.createElement ("div");
        container.innerHTML = i;
        container.style.border = "1px solid black";
        container.style.padding = "10px";
        container.onclick = function () {
            alert(locali);
        }
    }
    document.body.appendChild(container);
}

与之前提到的匿名函数解决方案相比,它的性能稍差(只有在称之为1000次的10次时才有意义),并且使用Visual Studio调试器(以及可能还有其他调试器)可以更好地工作。