JavaScript Cierres


Ejemplo

Cuando se declara una función, las variables en el contexto de su declaración se capturan en su alcance. Por ejemplo, en el código a continuación, la variable x está vinculada a un valor en el ámbito externo, y luego la referencia a x se captura en el contexto de la bar :

var x = 4; // declaration in outer scope

function bar() {
    console.log(x); // outer scope is captured on declaration
}

bar(); // prints 4 to console

Salida de muestra: 4

Este concepto de "capturar" el alcance es interesante porque podemos usar y modificar variables desde un alcance externo incluso después de que el alcance externo finalice. Por ejemplo, considere lo siguiente:

function foo() {
    var x = 4; // declaration in outer scope

    function bar() {
        console.log(x); // outer scope is captured on declaration
    }

    return bar;
    
    // x goes out of scope after foo returns
}

var barWithX = foo();
barWithX(); // we can still access x

Salida de muestra: 4

En el ejemplo anterior, cuando se llama a foo , su contexto se captura en la bar funciones. Así que incluso después de que regrese, la bar todavía puede acceder y modificar la variable x . La función foo , cuyo contexto se captura en otra función, se dice que es un cierre .

Datos privados

Esto nos permite hacer algunas cosas interesantes, como definir variables "privadas" que son visibles solo para una función específica o un conjunto de funciones. Un ejemplo artificial (pero popular):

function makeCounter() {
    var counter = 0;

    return {
        value: function () {
            return counter;
        },
        increment: function () {
            counter++;
        }
    };
}

var a = makeCounter();
var b = makeCounter();

a.increment();

console.log(a.value());
console.log(b.value());

Salida de muestra:

1
0

Cuando se llama a makeCounter() , se guarda una instantánea del contexto de esa función. Todo el código dentro de makeCounter() usará esa instantánea en su ejecución. Dos llamadas de makeCounter() crearán dos instantáneas diferentes, con su propia copia del counter .

Expresiones de función invocadas de inmediato (IIFE)

Los cierres también se usan para prevenir la contaminación global del espacio de nombres, a menudo mediante el uso de expresiones de función invocadas de inmediato.

Las expresiones de función invocadas de inmediato (o, quizás de manera más intuitiva, las funciones anónimas de ejecución automática ) son esencialmente cierres que se llaman inmediatamente después de la declaración. La idea general con IIFE es invocar el efecto secundario de crear un contexto separado que sea accesible solo para el código dentro de IIFE.

Supongamos que queremos poder hacer referencia a jQuery con $ . Considere el método ingenuo, sin utilizar un IIFE:

var $ = jQuery;
// we've just polluted the global namespace by assigning window.$ to jQuery

En el siguiente ejemplo, se utiliza un IIFE para garantizar que el $ esté vinculado a jQuery solo en el contexto creado por el cierre:

(function ($) {
    // $ is assigned to jQuery here
})(jQuery);
// but window.$ binding doesn't exist, so no pollution

Consulte la respuesta canónica en Stackoverflow para obtener más información sobre los cierres.