Question

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();
Was it helpful?

Solution

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();

Read more on hoisting here.


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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top