Skip to content Skip to sidebar Skip to footer

Binding Listeners Inside Of A For Loop : Variable Scope Miscomprehension

I've a variable scope problem and I don't understand why this occurs and how to get rid of it : var items = ['foo', 'bar']; for (var index in items) { var item = it

Solution 1:

Here's your fiddle example updated.

var items = ['foo', 'bar'];
for (var index in items) {
    (function() {
        var item = items[index]; 
        var selector = '.' + item + '-class';
        $(selector).bind('click', function() {
            console.log("class: " + $(this).attr('class'));
            console.log("selector: " + selector);
            console.log("item: " + item);
        });
    })();
}​

Creating an anonymous function will define a new scope for each of your defined variables

TIP: Try to create a separate function to do the bind, just to keep your code cleaner.

Solution 2:

It's always the same with these for-loops (google it). JavaScript does not have block scope but function scope, so when an item is clicked the one variable selector has the value it had after the last loop run (same for the variable item).

To solve the problem, you need another closure in you loop which stores the variables in its own scope. That means you need to execute a function for each loop run.

Solution 3:

The issue is not strictly about variable scope. The anonymous function runs at the time the click event is triggered, not when you are defining it in the loop. Consider the following which is functionally identical to your example:

var items = ['foo', 'bar'];

for (var index in items) {
    var item = items[index];
    var selector = '.'+item+'-class';
    $(selector).bind( 'click', test );
}
​
functiontest() {
    console.log("selector: "+selector);
}

This (hopefully) demonstrates what's happening: the global variable selector in the function is, at the time the function is being called, the same in both cases ("bar").

Solution 4:

var items = ['foo', 'bar'];
for (var index in items) {
    (function(i){  
    var item = items[i];
    var selector = '.'+item+'-class';
    $(selector).bind('click', function() {
            console.log("class: "+$(this).attr('class'));
            console.log("selector: "+selector);
            console.log("item: "+item);
        });
    })(index);
}

Fiddle here.

Solution 5:

Vars "selector" and "item" are references to a location where you store values, and the values of those two at the moment you click one of the htl elements is the one frome the last loop.

Post a Comment for "Binding Listeners Inside Of A For Loop : Variable Scope Miscomprehension"