0

私はjsfiddleでJavaScriptをいじっていて、奇妙な問題に遭遇しました。onclickfor ループ経由でイベント ハンドラーを設定できない理由がわかりません。

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

簡単で汚い解決策の1つは、このようなことをすることです

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

これは一般的なエラーです。iforループでインクリメントするグローバル変数です。ループが終了すると、iは4に等しくなります。次に、クリックハンドラー関数で、を表示しようとしています。arr[i].innerHTMLこれは現在、arr[4].innerHTMLです。arr[4]明らかに存在しないため、エラーが発生します。

簡単に修正するには、に変更alert(arr[i].innerHTML)alert(this.innerHTML)ます。this、クリックハンドラー関数のコンテキストでは、<TD>要素を参照します。

于 2012-10-22T18:15:31.320 に答える
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 に答える