JavaScript 101: Scope Closures

After looking at scope and hoisting last week, it’s time to tackle the often puzzling and feared notion of closure.

Closures are an integral part of the JavaScript language, and the fact that they are many a time misunderstood, dreaded, perhaps even intentionally avoided is quite unfortunate, and one should attempt to address this as soon as possible. Because closures are, first and foremost, a very powerful feature of the language, as long as they are recognized and used fittingly.

Closure what?

Closures in JavaScript stem from the language’s reliance on lexical scope. They occur naturally everywhere.

A closure is the mechanism by which a function is able to remember and access its lexical scope, despite that function executing outside of its lexical scope.

Let’s see it at work.

function foo() {
  var x = 1;

  function bar() {
    console.log(x);
  }

  return bar;
}

function baz = foo();

baz();

Now, there are a few things happening here, some more apparent than others.

It’s clear that bar() has lexical scope access to the scope of its containing foo().

But then, a reference to bar() is returned, as a value. foo() is executed and its returned value (bar()) is assigned to our new variable baz. Which is then invoked (baz()). The end result of this is a call to bar(), using a different identifier, and outside its original lexical scope.

What’s very interesting here is that once foo() is executed, its lexical scope doesn’t just get binned, but is kept and used by bar() when that is invoked later on via baz().

We conclude that bar() still has a reference to foo()‘s lexical scope, and that reference is what we call a closure.

There are many ways in which to pass inner functions to places outside their lexical scope, but all these scenarios have one thing in common: the inner function, called outside of its lexical scope defined at declaration time, will maintain a reference to that scope and will make use of it at execution time. Closure magic!

They’re everywhere

Everywhere, I tell you!

Let’s see a very familiar, closure-powered scenario:

function wait(msg) {
  setTimeout(function delay() {
    console.log(msg);
  }, 1000);
}

wait("The wait is over");

What happens here? Well, first of all, wait() is executed. 1000ms later, delay(), an inner function of wait() originally passed to setTimeout is finally executed as well. But delay() still has closure over wait(), and therefore has access to its lexical scope, and implicitly to msg. Closure magic!

We’ll leave this entry short, sweet and magical, but we’ll come back to closures in future posts, when we discuss how they are the driving force behind certain code patterns. That’s it for now!