Matt Mitchell
Matt Mitchell

Reputation: 41823

How do I use the value of a variable at declaration time in a JavaScript anonymous function?

This is a really basic question but...

I have some code like this

var arr = Array('blah.jpg','ha.jpg');
for (var i=0; i<array.length; i++)
{
    $('div#blah' + i).click(function() {
           $('img').attr('src', arr[i]); });
}

This should bind the div with id="blah0" to change all images to 'blah.jpg' when clicked. Similarly, clicking the div with id ="blah1" should change all images to 'ha.jpg'.

However, the anonymous function won't work because it will use the value of 'i' at the time of execution, i.e. 2. This means that clicking either div will try and set all images to arr[2] - a non-existent element (interestingly not throwing a JS error on my machine but that's another story...).

How can I get the anonymous function to be created using the value of 'i' at declaration time?

As a simpler example:

for (var i=0; i<10; i++)
{
    $('div#blah'+i).click(function() {
       alert(i)); });
}

This should display '0' when I click 'blah0', '1' when I click 'blah1' etc.

However, by default it will display '10' no matter which 'blah' i click.

Upvotes: 3

Views: 286

Answers (4)

Darko
Darko

Reputation: 38860

In this particular case you should be using a closure:

for (var i=0; i<10; i++)
{
    (function(j){
        $('div#blah'+j).click(function() { alert(j)); });
    })(i);        
}

(function(){ /* code */ })() denotes a self executing function, which implies that it will use and evaluate the value of i immediately in the loop as opposed to at click time.

Upvotes: 4

Matthew Crumley
Matthew Crumley

Reputation: 102725

Declare a new variable inside a function that creates a new click handler that gets the current value of i as a parameter:

function makeClickHandler(arr, local_i) {
    return function() {
        $('img').attr('src', arr[local_i]);
    };
}

var arr = Array('blah.jpg','ha.jpg');
for (var i=0; i<array.length; i++)
{
    $('div#blah' + i).click(makeClickHandler(arr, i));
}

Each instance of the function gets its own copy of local_i, that doesn't change each time.

Upvotes: 5

Matt Mitchell
Matt Mitchell

Reputation: 41823

I have this answer so far but bit of a hack:

var arr = Array('blah.jpg','ha.jpg');
for (var i=0; i<array.length; i++)
{
    eval("$('div#blah' + i).click(function() { $('img').attr('src', arr[" + i + "]); })");
}

Also:

for (var i=0; i<10; i++)
{
    eval("$('div#blah'+i).click(function() { alert(" + i + ")); });");
}

Upvotes: 0

shahkalpesh
shahkalpesh

Reputation: 33474

Have 1 more variable inside the loop and increment it after using it in the closure.


var j = 0;
for (var i=0; i<array.length; i++)
{
    $('div#blah' + j).click(function() {
           $('img').attr('src', arr[i]); });

    j++;
}

Upvotes: 0

Related Questions