Yeison Daza
4 min read

Understanding Closures in JavaScript

A closure is when a function is able to remember and access a lexical scope, even when that function is executed outside of that lexical scope.

Simple, right? Well, maybe not so much, but let’s go step by step and understand this.

Before diving deeper into the concept, you should check out:

Closures are widely used in JavaScript — you just need to know how to recognize them in code and understand the functionality implications they have.

Closures are available because the language implements lambdas and higher-order functions, and they’re a direct consequence of writing code using lexical scopes.

Let’s see this in code:

// Pruebalo: https://jsbin.com/dajocobugu/edit?js,console

function say() {
  var name = 'yeison';

  function sayName() {
    console.log(name);
  }

  // se retrona la definición de la función sayName
  return sayName;
}

// se asigna la ejecución de say a sayYeison
var sayYeison = say();

sayYeison();

We have a function that has an internal variable, which uses the variable name and returns the definition of the function sayName.

If we call a function without parentheses, we’re passing the function object itself.

If we call a function with parentheses, we pass the result of its execution. Higher-order functions in JavaScript

But when executing the function say — when it’s assigned to the variable sayYeison — shouldn’t its internal variable be cleaned up by the Garbage Collector since it’s no longer in use?

That’s not what happens, because when the function executes, it returns the definition of the inner function which holds a reference to that scope. That’s why the variable won’t disappear.

The inner scope is still in use, used by the function that is returned

The key thing to understand about closures is that we have a context and a function that uses it, allowing us to access the scope of that context.

Let’s look at another example.

// Pruebalo: https://jsbin.com/zebevucamo/edit?js,console
function makeCounter(counter, step) {

  function next() {
    return counter += step;
  }

  return next;
}

var counter2 = makeCounter(10,2);
counter2(); // sumamos dos, 12
console.log(counter2()); // sumamos dos, 14

var counter10 = makeCounter(50, 10);
counter10(); // sumamos 10, 60
console.log(counter10()); // sumamos 10, 70

By using closures, we can create functions with different contexts. This leads us to a very powerful pattern that we’ll explore in the next post.

Finally, let’s look at a practical application of closures, taken from JavaScript: The Good Parts (page 60).

We’re going to create a function to calculate the Fibonacci number.

// pruebalo: https://jsbin.com/laqikax/1/edit?js,console

var contador = 0;

var fibonacci = function (n) {
  // Contador para ver cuantas veces se ejecuta la función
  contador++;
  // recibimos un numero, si es menor de dos retornamos el numero,
  // si no realizamos dos llamadas recursivas a la función
  return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};

// Loop donde vamos pasando numero de uno en uno a la funcion fibonacci y mostrando el resultado
for (var i = 0; i <= 10; i += 1) {
  console.log(i + ': ' + fibonacci(i));
}

console.log(contador); //453

As you can see, the function fibonacci was called 453 times. With larger numbers, that count will grow exponentially. Let’s try to improve this by applying closures.

// Pruebalo: https://jsbin.com/bucuha/edit?js,console

var contador = 0;

var fibonacci = function () {
  var memo = [0, 1]; // array, para almacenar resultados

  var fib = function (n) {
    contador++; // contador para medir veces de ejecución

    var result = memo[n]; // se almacena la posición del array
    if (typeof result !== 'number') {//Se comprueba si el resultado ya existe
      result = fib(n - 1) + fib(n - 2); // se hace una llamada recursiva
      memo[n] = result; // y se almacena el resultado
    }
    return result;  // se retorna el resultado
  };
  return fib; // se retorna la definición de la función fib
}(); // se auto ejecuta la función para cuando se llame, se utilice la definición de la función fib

for (var i = 0; i <= 10; i += 1) {
  console.log(i + ': ' + fibonacci(i));
}

console.log(contador); //29

By using a closure that lets us store results in an array, the number of times the function is invoked is now just 29.

You can find more references on this topic at: