I've been doing some javascript reading, and I've gathered that a closure has access only to the closure "wrapping" it, or, you might say it's immediate parent. Now I've been playing a bit, and I see in this jsfiddle that even deep nested functions have access to to vars defined way up.
Can anyone please explain that? Or explain what have I got pletely wrong?
/function runNums() {
this.topVar = 'blah';
return function(){
(function() {
(function() {
console.log(topVar);
})();
})();
}
}
var someFunc = runNums();
someFunc();
I've been doing some javascript reading, and I've gathered that a closure has access only to the closure "wrapping" it, or, you might say it's immediate parent. Now I've been playing a bit, and I see in this jsfiddle that even deep nested functions have access to to vars defined way up.
Can anyone please explain that? Or explain what have I got pletely wrong?
http://jsfiddle/tPQ4s/function runNums() {
this.topVar = 'blah';
return function(){
(function() {
(function() {
console.log(topVar);
})();
})();
}
}
var someFunc = runNums();
someFunc();
Share
Improve this question
edited Mar 15, 2017 at 18:55
Let Me Tink About It
16.2k21 gold badges108 silver badges217 bronze badges
asked Dec 25, 2011 at 11:43
MeLightMeLight
5,5734 gold badges47 silver badges70 bronze badges
5
- Yes, closure "closes around" the variables that it can see at all parent levels. – Max Commented Dec 25, 2011 at 11:48
- An enclosed function can see all the way up?? – MeLight Commented Dec 25, 2011 at 11:51
- If you actually read that from somewhere, you might wanna stop reading materials that have blatant misinformation :P Of course it can access all parent levels. – Esailija Commented Dec 25, 2011 at 11:55
- See also stackoverflow./questions/1047454/what-is-lexical-scope. – helpermethod Commented Dec 25, 2011 at 12:12
- I would expect it to work this way just because that's also how scope works in general for nested functions/procedures in quite a wide variety of languages. If it didn't work this way also for closures it would be confusing. Or, to answer your question with two words: why not? – nnnnnn Commented Dec 25, 2011 at 12:24
4 Answers
Reset to default 7Without going too deep into the details, a closure
technically describes a array like variable
within the such called Activation Object that is handled from the javascript engine. An ActivationObject contains Variables declared by var
, function declarations and formal parameters.
That means, anytime a new function (-context) is invoked, internally a new Activation Object is created. That object is part of the new Execution Context
, a typicall EC looks like:
- this context variable
- Activation Object
- [[Scope]]
The interesting part here is [[Scope]]
. That variable contains all Activation Objects of all parent context and is filled when the EC is called. So now, when a function wants to access a variable, the name resolution process first looks into its own Activation Object, if nothing is found the search continues in the "Scope chain", which is just an Indexed search through our [[Scope]] variable (which again, is an array of parent contexts). Thats why we also speak a lot about "lexical scope" in ECMA-/Javascript.
Note: The above behavior is not described entirely, that would need several pages of text. Also it describes the ECMAscript3 262 specification. Things work a little different in ES5, but its still around the same thing
That is because the chain runs further up to the top context.
In the example, that would be:
window < runNums < anonymous < anonymous < anonymous
Variables living in any of these will be available in the last anonymous function. In runNums, only variables living in runNums or window will be available. In the first anonymous function, only its variables and those living in runNums or window will be available, etc.
this is nothing but the Window object here.
Here runNums is a global function and runNums() is equal to window.runNums(). So this is window and this.topVar is window.topVar. Obviously it will be accessible from anywhere.
Try this and see the difference
var someFunc = new runNums();
someFunc();
The deep nested functions have not been executed. You did not return them for executing.