Understanding Closures in Javascript

Michael Ries
Code Monkey
5 min readSep 15, 2017

--

Closures are a powerful and widely used feature of Javascript, yet they can be confusing to a novice programmer. A solid understanding, however, is key to better code. Before we dive into some common use cases, let’s get to the heart of what a closure is and does.

Note: This article assumes that you are familiar with variable scope in Javascript.

MDN defines a closure as:

A closure is the combination of a function and the lexical environment within which that function was declared.

To understand this, we must first define a lexical environment. When a function is declared, the lexical environment for that function is created to store the variables and functions that are declared within it. The lexical environment for a function can be thought of as a map between the variable names and their values in memory. So when I write

function foo() {
var a = 10;
}

the lexical environment for the foo() function will contain a string ‘a’ and a corresponding reference to a memory location what will be initialized to the value 10. (Note: this is probably not strictly true, as in most cases the value will be an object reference, but that’s a complication we can ignore for now.)

Every function is declared within an environment. It could be the global environment, but is more commonly that of another function. Every time you define a function, you are creating a closure that combines it and the lexical environment of its parent. For example,

function creature(name) {
var myName = name;
function getName() { // we're creating a closure here
return myName;
}
return { getName };
}
var rat = creature('rat');
rat.getName();

When getName() is defined, a closure is created that combines the lexical environment of getName() with that of creature(). This allows getName() to access the value of myName. A key point to notice here is that the closure exists (and therefore myName) even after the creature() method has finished executing.

To demonstrate further, let’s add a little more complexity to our creature by enabling changes to the name:

function creature(name) {
var myName = name;
function getName() { // we're creating a closure here
return myName;
}

function setName(name) { // we're creating a closure here
myName = name;
}
return { getName, setName };
}
var rat = creature('monster');
rat.getName(); // returns 'monster'
rat.setName('Giant Rat');
rat.getName(); // returns 'Giant Rat'

See how the value of myName can be manipulated? That’s because the closure provides references to the actual variables and not just static values.

Furthermore, although we have created a closure for getName() and another closure for setName(), they both reference the same myName variable through the creature() lexical environment.

Each time the outer function is executed, a new execution context is created. Discussion of execution contexts is outside the scope of this post, but the consequence is that you get new closures each time you run the creature() function.

var rat = creature('Giant Rat');
var spider = creature('Giant Spider');
rat.getName(); // returns 'Giant Rat'
spider.getName(); // returns 'Giant Spider'

Common Use Cases

Private Variables and Methods

Our creature() is an example of a common use case for closures: to create private variables and/or functions. The only outside access to the myName variable is through the getName() and setName() methods. This helps to avoid variable name clashes and encourages good object-oriented design.

Event Handlers and Callbacks

The following examples all use closures.

var time = 1000;
var message = 'Time is up!'
function handleTimeout() { // a closure here allows this function
console.log(message); // to access global variable message
}
setTimeout(handleTimeout,time);///////////////////////////////////////////////////////////var multiplier = 5;
[0,1,2,3,4,5,6].map(element => (element * multiplier));
///////////////////////////////////////////////////////////var submitted = false;
var handleSubmit = event => {
submitted = true;
// handle form submission here
}

Stateful functions

Stateful functions are functions that store state and return a function that depends on the internal state. Consider this example.

// this is my preferred syntax, but some people get confused
const multiplier = multiple => value => value * multiple
// it can also be written this way:
function multiplier(multiple) {
return value => multiple * value;
}
const doubler = multiplier(2);
doubler(2); // returns 4
doubler(10); // returns 20;

Currying

Functional programming is a hot topic these days, as it generally makes programs more testable and predictable and therefore leads to fewer bugs. Currying is often used to transform a function that takes multiple parameters into one that takes fewer parameters.

As an example, suppose we have a function to add two variables.

function add(a, b) { return a + b; }
add(2,3) // returns 5

Using a closure lets us write this as

const add = a => b => a + b;// or alternatively
function add(a) {
return (b) => a + b;
}
add(2)(3) // returns 5

I won’t go further into currying or functional programming as this is a topic that I’m just starting to learn.

Summary

  • A closure is created whenever you declare a function.
  • Closures combine the function and its environment to that of its parent, allowing access to functions and variables of the parent.
  • The closure persists after the execution of the parent completes.
  • If the parent function is invoked again, new closures will be created for its inner functions, additional to any closures that already exist.
  • Closures enable some really cool and powerful stuff.

I’m sure that many of you noticed that our creature() looks and works a lot like a class object, except that we didn’t use the class keyword, there is no prototype, new new keyword, and no Object.create() or Object.assign(). If you cut your object-oriented programming teeth on languages that use classical inheritance as I did (Java, C#, Ruby) this may be a little surprising. It turns out that there are many ways to create objects in Javascript and most of them are better than classical inheritance. I plan to cover inheritance and object creation in my next post.

Finally, keep in mind that like you, I’m always learning. If you have questions or see something that needs clarification (or is downright wrong) please bring it to my attention!

--

--

Michael Ries
Code Monkey

Solving complex problems one simple problem at a time.