Question

My case:

var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++)
{
    tds[i].onclick = function()
                      {
                          alert(i);
                      };
}

Expected outcome: Alert the number of TD.

However if there are 6 TDs, the returned value will always be the last value of "i". (6) How could i make the "i" value to remain at it's value when added to the function?

Thanks!

http://jsfiddle.net/nuKEK/11/

Was it helpful?

Solution

You need to make a closure to capture the i value. Something like this

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

var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++){
    tds[i].onclick = createFunction(i);
}

DEMO: http://jsfiddle.net/nuKEK/12/

OTHER TIPS

You can pass i to another function in order to get its value rather than a reference to it. In javascript, numbers are passed by value.

tds[i].onclick = (function(x) {
    return function() {
        alert(x); // alerting x, i's value
    };
})(i); // passing i as parameter x

If that self-executing anonymous function looks a little hairy in the context of your loop, you could try Array.prototype.forEach() instead:

[].forEach.call(document.getElementsByTagName("td"), function(td, i) {
    td.onclick = function() {
        alert(i);
    };
});

[edit] Have a look at these options and their performance.

This is one of the common mistakes in Javascript in that it is not block scoped like most languages. It is function-scoped.

You need to create a closure around the onclick to achieve this.

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

    (function (index) {
        tds[index].onclick = function() {
            alert(index);
        };
    })(i);

}
var tds = document.getElementsByTagName("td");
for(i=0;i<tds.length;i++)
{
    addClick(tds, i);
}


function addClick(where, i) {
    where[i].onclick = function()
    {
        alert(i);
    };
}

You will have to force the value into a scope that will still exist when the callback is fired.

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

Otherwise, the value for i will always be the last index

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top