0

我在 jsfiddle 上弄乱了一些 javascript,遇到了一个奇怪的问题。我似乎无法弄清楚为什么我无法onclick通过 for 循环设置事件处理程序:

html:

<table border="1" cellspacing="1" width="500">
    <tr id="headerRow">
        <td>Header1</td>
        <td>Header2</td>
        <td>Header3</td>
        <td>Header4</td>
    </tr>
    <tr>
        <td>books</td>
        <td>red</td>
        <td>peas</td>
        <td>321</td>
    </tr>
    <tr>
        <td>tapes</td>
        <td>blue</td>
        <td>jello</td>
        <td>654</td>
    </tr>
</table>

在 DOM 中执行的 js 准备就绪:

var arr = document.getElementById('headerRow')
    .getElementsByTagName("td");

// Why does this work??
/*arr[0].onclick = function() { alert(arr[0].innerHTML); };
arr[1].onclick = function() { alert(arr[1].innerHTML); };
arr[2].onclick = function() { alert(arr[2].innerHTML); };
arr[3].onclick = function() { alert(arr[3].innerHTML); };
*/

//But this doesn't????
for(var i = 0; i < arr.length; i++) {
    arr[i].onclick = function() { alert(arr[i].innerHTML); };
}

http://jsfiddle.net/xzmMj/4/

4

3 回答 3

4

i不会像您想要的那样包含“当前索引”,而是最后一个值i,即arr.length

一个快速的肮脏解决方案是做这样的事情

for(var i = 0; i < arr.length; i++) {
    (function(_i){
        arr[_i].onclick = function() { alert(arr[_i].innerHTML); };
    })(i);
}

i它的作用是在您正在执行的语句的闭包中捕获一个新变量中的当前值_i,因此它会一直存在并且是您每次调用 onclick 处理程序时期望的值。

于 2012-10-22T18:09:12.407 回答
1

您需要一个闭包,否则会arr[i]在备用范围内执行并爆炸。

for(var i = 0; i < arr.length; i++) {

    arr[i].onclick = function(text) { 
        return function () {
            alert(text); 
        };
    }(arr[i].innerHTML);
}

http://jsfiddle.net/xzmMj/5/

于 2012-10-22T18:12:30.427 回答
1

这是一个常见的错误。i是您在 for 循环中递增的全局变量。当循环结束时,i 将等于 4。然后在您的点击处理程序函数中,您尝试显示arr[i].innerHTML,即 now arr[4].innerHTMLarr[4]显然不存在,所以你得到一个错误。

为了便于修复,请更改alert(arr[i].innerHTML)alert(this.innerHTML). this,在单击处理函数的上下文中,将引用<TD>元素。

于 2012-10-22T18:15:31.320 回答