EDIT: thanks for the answers, I think I get it now. It requires an understanding of scope and hoisting. Below is a new example that I think illustrates both well:
var a = function (){
alert(x);
}
var x = 1;
(function(){
var x = 2;
a();
})();
The above alerts 1. Lexical scope is illustrated by the fact that this alerts 1 and not 2, and hoisting is illustrated by the fact that the "var x = 1" line comes after the declaration of a and definition of the anonymous function with the "alert(x)". Allegedly, hoisting means that the above is equivalent to the below (source: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html):
var x;
var a = function (){
alert(x);
}
x = 1;
(function(){
var x = 2;
a();
})();
So since x is effectively initialized before the function definition, the x in "alert(x)" is the same x that subsequently gets set to 1.
Since JS uses lexical scope, the line "var x = 2" does not override the x associated with a.
Is that about right?
---original question---
I've spent pretty much all day trying to figure this out. I've read a few articles on scope and closures in Javascript, but this still eludes me.
I'm told that a function's lexical environment is created when the function is defined, not when it is executed.
So if there is no variable called x declared anywhere in my program, then what is the closure environment for the anonymous function that a points to when I do this?:
var a = func(){
var y = 7; //just for illustrative purposes
alert(x);
});
My understanding is that an environment is a mapping of variable names to values...so it would be
y: 7
x: ?
Is that correct? The following code alerts "10":
(function (){
var a = function(){
alert(x);
};
var x = 10;
a();
})();
My guess would be that when a is called, the JS checks the closure environment for a mapping for x and finds none, and subsequently checks the local environment and finds the x set to 10 by "var x = 10". Is that right?
If that were the case, then I would expect the following would also work, and yet it does not:
var a = function(){
alert(x);
};
(function (){
var x = 10;
a();
})();
What I would expect to happen is that, when a is executed, and "alert(x);" is run, it checks the closure environment for x, finds none, then checks the outer environment where "var x = 10" is and finds that x. But instead I get an error that x isn't defined.
Maybe it would help if I could know what 'preparatory' work is done by the interpreter when the anonymous function that a is set to is initially defined--i.e. when the interpreter encounters the x in "alert(x)".
Thanks
the JS checks the closure environment for a mapping for x and finds none
In fact it does find one. The position of the var statement does not matter, the name x is still bound to the closure of the outer function. You can think of the declarations being collected during the parsing step and moved to the front (this process is called hoisting).
Thr process of walking up the scopes surrounding an expression in the source code is called lexical binding.
For your second example to work you'd need dynamic binding, which JS does not support (except for globals).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With