4

With JavasScript, say there is an innerFunction() defined within an outerFunction(). If you attempt to call the innerFunction(), outside of the outerFunction(), there will be an error as it is not defined within the scope.
However, if while in the outerFunction(), you assign the innerFunction() to an event, say a click event, for some outside element, like a button, then the innerFunction() can be called from that scope of the button, whatever it may be. So why are you able to make this second call to innerFunction() froma different scope.

I have a working example: http://jsfiddle.net/rcmoore38/gPrMk/

The initial changeColor() call does not work, but when changeColor() is assigned to the button, it can be called via the button.

Thank you!

user4815162342
  • 1,638
  • 2
  • 17
  • 23
  • The functions are referenced in the event handlers, and they are all within scope ? – adeneo Jul 26 '13 at 16:07
  • Why can `changeColor()` be called through the button, but not initially, I understand when `changeColor()` is assigned to the button, it is within scope, but the button is not itself within scope. – user4815162342 Jul 26 '13 at 16:08
  • 1
    In your code the line `$("#pid").css("color", function() { return get_random_color()});` can be changed to `$("#pid").css("color", get_random_color());` without loss of functionality. – Halcyon Jul 26 '13 at 16:10
  • Thanks @FritsvanCampen, I'm never sure when I need to include the function wrapper. – user4815162342 Jul 26 '13 at 16:15

1 Answers1

2

There is no "scope of the button". What happens is that you're assigning the event listener from a scope where the inner function is visible, and that's all that matters in JavaScript. Scope in JS is about where functions are declared.

In your example:

$("#b").click(function() { changeColor() });

the function changeColor is available via closure inside the anonymous function, because it's declared in an outer scope. When you define a nested function, all variables and functions from the parent functions will be available inside it. So when the element is clicked and the anonymous function is called, it still has a reference to changeColor, and is able to call it.

You could also set the event handler without using a closure, like this:

$("#b").click(changeColor);

As I said, the important thing is that changeColor is in scope when you reference it (not when it's actually called, in this case, by the browser).

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • Just to clarify, `changeColor()` would initially be able to access all variables in `gen()`, but after the initial call, it would only have its local variables, which would carry over like static variables in C? – user4815162342 Jul 26 '13 at 16:13
  • No, all variables from all outer scopes are available within `changeColor`, whenever it's called - as long as you call it from somewhere where `changeColor` itself is visible. – bfavaretto Jul 26 '13 at 16:14
  • And if those variables were to be changed in the outer function, `gen()`, they would be changed in the inner function, too, because they are all just references? – user4815162342 Jul 26 '13 at 16:18
  • 2
    Yes, they will change (the classic example is a [closure inside a `for` loop](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example)), unless you create new scopes to hold the different states of the variable. – bfavaretto Jul 26 '13 at 16:20