I was planning to post a write up on closures in javascript but it made sense to first introduce you to concept of lexical scoping (or static scoping).

In JavaScript, functions have lexical scope. This means that functions create their environment (scope) when they are defined, not when they are executed.  With static scope, a variable always refers to its top-level environment. This is a property of the program text and unrelated to the runtime call stack. Because matching a variable to its binding only requires analysis of the program text, this type of scoping is called lexical scoping.

Consider the two examples given below:

Example 1:

function f1() {
    var a = 20;
    return function () { alert(a); }
}

var b = f1();
b();

Example 2:

function f1() {
    var a = 20;
    return f2
}

function f2() {
    alert(a);
}

var b = f1();
b();

 

In example 1 with the anonymous function, the command b() will generate a pop up with 20 whereas in example 2, you will get a has undefined.

This is because, when the anonymous function in example 1 was created, variable ‘a’ was present in the environment and hence, you get 20 as pop up. But in example 2, the in the function f2(), there isn’t a variable ‘a’ declared and assigned any value.

When a function is defined, it "remembers" its environment, its scope chain. This doesn't mean that the function also remembers every single variable that is in scope. Just the opposite—you can add, remove or update variables inside the scope of the function and the function will see the latest, up-to-date state of the variables. This behaviour gives JavaScript great flexibility—you can add and remove variables and add them again, and it's totally fine, because all it needs to know is how to access its scope and not what this scope used to contain at some point in time.

“Lexical scope” in general is the idea that

  • an identifier at a particular place in a program always refers to the same variable location — where “always” means “every time that the containing expression is executed”, and that
  • the variable location to which it refers can be determined by static examination of the source code context in which that identifier appears, without having to consider the flow of execution through the program as a whole.