Closures Javascript

Logo Javascript

Ya hemos visto cómo definir funciones o declarar expresiones de función para poder pasar las funciones como parámetros de otras funciones. Ahora vamos a ver qué es el concepto closures Javascript o cierres en Javascript.

Funciones anidadas

Antes de entra en detalle sobre los closures Javascript lo primero que tenemos que saber es que las funciones en Javascript se pueden anidar. Es decir, podemos definir una función dentro de otra función.

function exterior(parametros) {
  function interior(parametros) {
     sentencias;
     return interior;
   }
   return exterior;
}

exterior(parametros);

En esta estructura tenemos una función interna que por un lado puede acceder a la información que tiene la función exterior. De forma externa solo podemos invocar a la función exterior, pero nunca a la interior.

Por ejemplo, si queremos definir una función que sume dos números elevados al cuadrado podríamos tener el siguiente código:

function addSquare(a,b) {
    function square (x) {
        return x*x;
    }
    return square(a)+square(b);
}

console.log(addSquare(2,3)); // 13
console.log(square(2));      // No se puede invocar

Como podemos ver la función externa addSquare tiene una función interna que se llama square que es invocada y utilizada para devolver un valor. Además, mediante el código, vemos que la función square no puede ser invocada de forma externa.

Closures Javascript

En esta anidación de funciones los closures Javascript se producen cuando la función retorna una función y el contexto asociado a dicha función.

Por ejemplo vamos a definir una función anidada la cual contenga en un primer nivel la información de la persona que queremos saludar y que anide una función que realice el saludo a dicho nombre. Esta función va a devolver tanto la función que saluda, como el contexto asociado, es decir, la variable que contiene el nombre.

Definiremos el closure Javascript de la siguiente forma:

function saludo() {
    let texto = 'Buenos días';
    function saludoDia(){
        console.log(texto);
    }
    return saludoDia;  
}

let saludar = saludo();
saludar();  // Buenos días

Podemos apreciar que la función interna tiene acceso a los valores declarados en la función externa, los cuales se retornan y permanecen creados mientras exista la función.

Los contextos asociados se pueden entender mejor si modificamos la función externa para poder pasarle el mensaje de saludo y la interna para pasarle el nombre de la persona a saludar, quedando de la siguiente manera:

function saludo(mensaje) {    
    function saludoNombre(nombre){
        console.log(`${mensaje}, ${nombre}`);
    }
    return saludoNombre; 
}

Podemos crear diferentes contextos con el mensaje del saludo de la siguiente manera:

let saludarTarde = saludo("Buenas tardes");
let saludarNoche = saludo("Buenas noches");
let nombre="Víctor";

saludarTarde(nombre);  // Buenas tardes, Víctor
saludarNoche(nombre);  // Buenas noches, Víctor

El contexto demarcado por la variable saludo perdura durante toda la función.

Vemos que la función es la misma, pero con contextos diferentes marcados por el parámetro de la función externa. Es aquí dónde tenemos nuestros closures Javascript.

Además podríamos invocar a la función pasándole tanto el parámetro externo como el parámetro interno.

saludo("Buenos días")("Luis");


Mejora esta página