The closure rule is: functions are executed using the scope chain that was in effect when they are defined.
In the setTimeout callback function below, x is not yet in scope at the time of definition. Therefore, the program should print undefined, but it prints 7, why? what am I missing?
var foo = function () {
setTimeout(function (){
console.log(x);
}, 3000);
};
var x = 7;
foo();
Or, is it because the above code is exactly same as the below?
var x = 7;
var foo = function () {
setTimeout(function (){
console.log(x);
}, 3000);
};
foo();
x is not yet in scope at the time of definition
This is not true. The reason is hoisting. Basically, JavaScript will move any var
or named function
to the top of the containing scope. So what you actually have is something more like this:
// these variables are hoisted
var x;
var foo;
// then the variables are assigned.
foo = function () {
setTimeout(function (){
console.log(x);
}, 3000);
};
x = 7;
foo();
Also, this is accurate:
functions are executed using the scope chain that was in effect when they are defined.
But your interpretation is not accurate. They have access to the scope in which they were defined, but not at the point they were defined. Variables can have values that change over time, and the functions declared in those scopes will use those up to date values from that scope. There is no time machine.
So when the nested function executes, foo
is 7
because in that scope, at that moment, foo
really is 7
.