Closure in JavaScript

Closure is one of those terms you hear thrown around a lot in JavaScript development, but it’s often misunderstood and mistaken for scope. Scope is related and plays an important role in closure, but is not the same thing.

Closure is when a function has access to its original context. Here’s the Mozilla Developer Network’s take on closure:

A closure is a special kind of object that combines two things: a function and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created.

An example:

function speak() {
    var greeting = 'hi';
    function saySomething() {
        console.log(greeting);
    }
    saySomething();
}
speak(); //hi

In this example, saySomething is a closure–it is a function that has access to its original context. Put differently, it is a function AND the environment in which it was created because it can access greeting, a variable from the parent function’s scope. greeting is not part of saySomething‘s scope.

Another example:

function speak(name) {
    var greeting = 'hi';
    function saySomething() {
        console.log(name + ' says ' + greeting);
    }
    saySomething();
}
speak('billy'); //billy says hi

In this example, speak defines a variable AND takes an argument. saySomething is still a closure–it can reference variables and parameters that are part of its environment.

A common misconception about closure is that you have to return a function for a closure to exist. This is NOT true. However, let’s expand the existing example by returning the saySomething function instead of executing it:

function speak(name) {
    var greeting = 'hi';
    function saySomething() {
        console.log(name + ' says ' + greeting);
    }
    return saySomething;
}
var billySpeaks = speak('billy');
var nobodySpeaks = speak('nobody');
billySpeaks();   //billy says hi
nobodySpeaks();  //nobody says hi

You’d think name and greeting would only be accessible at the time of execution, but that’s obviously not the case. That’s because local variables and arguments that are in scope at the time a closure is created remain accessible–they are part of the environment.

In the preceding example, speak is a closure that consists of the parameter name, the local variable greeting and the function saySomething when it was created. Therefore, billySpeaks and nobodySpeaks have access to them after execution has finished.

References

More JavaScript