3

I'm trying to wrap my head around a scope issue. Take the two examples:

a)

var sels = ['.a', '.b', '.c'];
while ( (var sel = fieldsets.shift()) !== undefined ) { 
    (function(sel) {
        $(sel).click(function() {
            console.log(sel);
        });
    })(sel);
}

In this example, when one of the referenced elements is clicked, the output will be .a, .b, or .c.

b)

var sels = ['.a', '.b', '.c'];
while ( (var sel = fieldsets.shift()) !== undefined ) { 
    $(sel).click(function() {
        console.log(sel);
    });
}

In this example, a click will result with undefined.

I'm clearly misunderstanding how scope is applied in these two examples, because as I see it, when .click is called in either case, sel no longer exists at all.

What is the difference in the way scope is applied between these two cases?

Community
  • 1
  • 1
JoBu1324
  • 7,751
  • 6
  • 44
  • 61
  • In the first example, you're capturing the value of `sel` for the handler to have access to the correct one. In the second example, `sel` is a variable available to all handlers that will have the last item from looping (which is `undefined`). – Ian May 08 '13 at 17:08
  • possible duplicate of [Javascript closure inside loops - simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Bergi May 08 '13 at 17:12
  • It does look like a duplicate, but the stated question and especially the answer are more useful for understanding the issue (and not simply coming up with a solution). I'll let the community decide how to treat this question. – JoBu1324 May 08 '13 at 17:26

1 Answers1

3

The key is in this statement of yours:

... because as I see it, when .click is called in either case, sel no longer exists at all.

In a language like C, that would be true. Not JavaScript! When a function is instantiated (as is done in both of your examples to create the event handlers), it "captures" the enclosing context. When the function is executed, that context remains available, unlike in a stack-based language. (The topic of "closures" is what we're talking about, and you can find much more lucid explanations elsewhere than I could type in here in this brief answer.)

The key difference is that your first example introduces a new layer. In that example, each instantiated event handler effectively gets its own private "sel" variable, that being the parameter to the anonymous wrapper function. The outer "sel" is made inaccessible by that because the names match.

In the second example, because all the event handlers share access to the same unique variable "sel", they all see the same thing when they're called: the value of "sel" as it was at the end of the loop. That value would be undefined because that's when your loop stops.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Closures is exactly where this answer needed to go. Another key to the javascript language just fell into place! – JoBu1324 May 08 '13 at 17:27