Reputation: 21641
One more JavaScript scoping problem. I believe this is not related to 'hoisting'.
I've a small block of code here - http://jsfiddle.net/0oqLzsec/2/
var c = function(){
var x = 'before',
callBefore = function(){
alert(x);
},
callAfter = function(){
_callAfter();
};
return{
callBefore : callBefore,
callAfter : callAfter
}
var y = 'after';
function _callAfter(){
alert(y);
}
};
var obj = c();
obj.callBefore();
obj.callAfter();
callAfter()
always alerts 'undefined' even if the variable y is defined before _callAfter()
. But If I move the variable y declaration before variable x it is working.
I'm wondering if callAfter()
can _callAfter()
which is defined below, why can't it read variable y?
Upvotes: 1
Views: 148
Reputation: 92274
It is related to hoisting, var y
is moved to the top of the function, but the assignment (y = 'after'
) is not, so it never runs because it's after the return statement
.
The JS engine rewrites your code to look something like:
var c = function(){
// functions also get hoisted to the top
function _callAfter(){
alert(y);
}
var x = 'before',
callBefore = function(){
alert(x);
},
callAfter = function(){
_callAfter();
},
// y declaration is hoisted to the top of the function
y;
return {
callBefore : callBefore,
callAfter : callAfter
};
// the assignment never gets called because it's after the return
y = 'after';
};
Upvotes: 2
Reputation: 303215
_callAfter
and y
are both hoisted, which makes them known as local variables through the function invocation. The _callAfter
function is able to be called (as you do), and it also closes over the variable y
. However, this variable does not get a value assigned before you return from the c
function. Thus, you get undefined
. It is the same if you put var y;
BEFORE the return, and y='after';
after the return.
In other words, the following two are equivalent:
function foo(){
var a;
return function(){ return a };
a = 42; // never runs
}
alert( foo()() );
function bar(){
return function(){ return a };
var a = 42;
}
alert( bar()() );
Here's an example showing that the local variable is hoisted and closed over, even when the function literal occurs before the var
in code:
function build() {
return function(newValue) {
alert("was: " + oldValue);
oldValue = newValue;
alert("now: " + oldValue);
}
var oldValue = 42;
}
f = build();
f(17);
// was: undefined
// now: 17
f(99);
// was: 17
// now: 99
Upvotes: 3