0

I was messing around with some javascript, on jsfiddle, and ran into a strange issue. I can't seem to figure out why I am unable to set onclick event handlers via a for loop:

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>

js executed in DOM ready:

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/

1

3 Answers 3

4

i will not contain the "current index" like you are intending, but rather the last value i was, ie arr.length

One quick n dirty solution would be to do something like this

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

what this does is captures the current value of i in a new variable _i within the closure of the statement you're executing, so it'll stay around and be the value you'd expect every time your onclick handler is called.

Sign up to request clarification or add additional context in comments.

1 Comment

Interesting.. thank you.
1

You need a closure, otherwise the arr[i] executes in an alternate scope and blows up.

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/

1 Comment

Cool, thanks. Makes sense. I'll have to get more friendly with "Closures"
1

This is a common error. i is a global variable that you're incrementing in the for loop. When the loop finishes, i will be equal to 4. Then in your click handler function, you're trying to display arr[i].innerHTML, which is now arr[4].innerHTML. arr[4] obviously doesn't exist, so you get an error.

For an easy fix, change alert(arr[i].innerHTML) to alert(this.innerHTML). this, in the context of the click handler function, will refer to the <TD> element.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.