Skip to content
Skip to content
Menu
Info Cafe
Info Cafe

Una guía sencilla para ayudarte a entender los cierres en JavaScript

By admin on enero 20, 2021

Los cierres en JavaScript son uno de esos conceptos que a muchos les cuesta entender. En el siguiente artículo, voy a explicar en términos claros lo que es un cierre, y voy a llevar el punto a casa usando ejemplos de código simples.

Un cierre es una característica en JavaScript donde una función interna tiene acceso a las variables de la función externa (que encierra) – una cadena de alcance.

El cierre tiene tres cadenas de ámbito:

  • tiene acceso a su propio ámbito – las variables definidas entre sus llaves
  • tiene acceso a las variables de la función externa
  • tiene acceso a las variables globales

Para los no iniciados, esta definición puede parecer un montón de jerga

Pero ¿qué es realmente un cierre?

Veamos un sencillo ejemplo de cierre en JavaScript:

function outer() { var b = 10;
function inner() {
var a = 20;
console.log(a+b);
}
return inner;
}

Aquí tenemos dos funciones:

  • una función externa outer que tiene una variable b, y devuelve la función inner
  • una función interna inner que tiene su variable llamada a, y accede a una variable outerb, dentro de su cuerpo de función
  • El ámbito de la variable b se limita a la función outer, y el alcance de la variable a se limita a la función inner.

    Invoquemos ahora la función outer(), y almacenemos el resultado de la función outer() en una variable X. Invocamos entonces la función outer() una segunda vez y la almacenamos en la variable Y.

    Veamos paso a paso lo que ocurre cuando se invoca por primera vez la función outer():

  1. Se crea la variable b, se limita su ámbito a la función outer() y se establece su valor a 10.
  2. La siguiente línea es una declaración de función, por lo que no hay nada que ejecutar.
  3. En la última línea, return inner busca una variable llamada inner, encuentra que esta variable inner es en realidad una función, por lo que devuelve el cuerpo completo de la función inner.
  4. El contenido devuelto por la sentencia return se almacena en X.
    Así, X almacenará lo siguiente:
    function inner() {
    var a=20;
    console.log(a+b);
    }
  5. La función outer() termina de ejecutarse, y todas las variables dentro del ámbito de outer() ya no existen.

Esta última parte es importante de entender. Una vez que una función completa su ejecución, cualquier variable que fue definida dentro del ámbito de la función deja de existir.

El tiempo de vida de una variable definida dentro de una función es el tiempo de vida de la ejecución de la función.

Lo que esto significa es que en console.log(a+b), la variable b sólo existe durante la ejecución de la función outer(). Una vez que la función outer ha finalizado su ejecución, la variable b deja de existir.

Cuando la función se ejecuta por segunda vez, las variables de la función se crean de nuevo, y viven sólo hasta que la función finaliza su ejecución.

Así, cuando outer() se invoca la segunda vez:

  1. Se crea una nueva variable b, su ámbito se limita a la función outer(), y su valor se establece en 10.
  2. La siguiente línea es una declaración de función, por lo que no hay nada que ejecutar.
  3. return inner devuelve todo el cuerpo de la función inner.
  4. El contenido devuelto por la declaración de retorno se almacena en Y.
  5. La función outer() finaliza su ejecución, y todas las variables dentro del ámbito de outer() dejan de existir.

El punto importante aquí es que cuando la función outer() se invoca por segunda vez, la variable b se crea de nuevo. Además, cuando la función outer() termina de ejecutarse por segunda vez, esta nueva variable b vuelve a dejar de existir.

Este es el punto más importante a tener en cuenta. Las variables dentro de las funciones sólo nacen cuando la función se está ejecutando, y dejan de existir una vez que las funciones completan su ejecución.

Ahora, volvamos a nuestro ejemplo de código y veamos X y Y. Como la función outer() al ejecutarse devuelve una función, las variables X y Y son funciones.

Esto se puede comprobar fácilmente añadiendo lo siguiente al código JavaScript:

console.log(typeof(X)); //X is of type function
console.log(typeof(Y)); //Y is of type function

Como las variables X y Y son funciones, podemos ejecutarlas. En JavaScript, una función se puede ejecutar añadiendo () después del nombre de la función, como X() y Y().

Cuando ejecutamos X() y Y(), estamos ejecutando esencialmente la función inner .

Examinemos paso a paso lo que ocurre cuando X() se ejecuta la primera vez:

  1. Se crea la variable a, y su valor se establece en 20.
  2. JavaScript intenta ahora ejecutar a + b. Aquí es donde las cosas se ponen interesantes. JavaScript sabe que a existe ya que lo acaba de crear. Sin embargo, la variable b ya no existe. Como b forma parte de la función externa, b sólo existiría mientras la función outer() está en ejecución. Como la función outer() terminó de ejecutarse mucho antes de que invocáramos X(), cualquier variable dentro del ámbito de la función outer deja de existir, y por tanto la variable b deja de existir.

¿Cómo maneja esto JavaScript?

Cierres

La función inner puede acceder a las variables de la función que la encierra debido a los cierres en JavaScript. En otras palabras, la función inner conserva la cadena de alcance de la función adjunta en el momento en que se ejecutó la función adjunta, y por lo tanto puede acceder a las variables de la función adjunta.

En nuestro ejemplo, la función inner había conservado el valor de b=10 cuando se ejecutó la función outer(), y siguió conservándolo (cerrándolo).

Ahora consulta su cadena de alcance y se da cuenta de que sí tiene el valor de la variable b dentro de su cadena de alcance, ya que había encerrado el valor de b dentro de un cierre en el momento en que se había ejecutado la función outer.

Así, JavaScript conoce a=20 y b=10, y puede calcular a+b.

Puedes comprobarlo añadiendo la siguiente línea de código al ejemplo anterior:

Abre el elemento Inspect en Google Chrome y ve a la Consola. Puedes expandir el elemento para ver realmente el elemento Closure (mostrado en la antepenúltima línea de abajo). Observa que el valor de b=10 se conserva en el Closure incluso después de que la función outer() termine su ejecución.

La variable b=10 se conserva en el Closure, Cierres en Javascript

Volvamos ahora a revisar la definición de cierres que vimos al principio y veamos si ahora tiene más sentido.

Pues la función interior tiene tres cadenas de alcance:

  • acceso a su propio ámbito – variable a
  • acceso a las variables de la función outer – variable b, que encerraba
  • acceso a cualquier variable global que pueda estar definida

Cierres en acción

Para hacer entender el punto de los cierres, vamos a aumentar el ejemplo añadiendo tres líneas de código:

Cuando ejecutes este código, verás la siguiente salida en el console.log:

a=20 b=10
a=20 b=11
a=20 b=12
a=20 b=10

¡Examinemos este código paso a paso para ver qué ocurre exactamente y ver los cierres en Acción!

var X = outer(); // outer() invoked the first time

La función outer() se invoca la primera vez. Se producen los siguientes pasos:

  1. Se crea la variable b y se establece como 10
    Se crea la variable c, y se establece en 100
    Llamemos a esto b(first_time) y c(first_time) para nuestra propia referencia.
  2. La función inner es devuelta y asignada a X
    En este punto, la variable b está encerrada dentro de la cadena de alcance de la función inner como un cierre con b=10, ya que inner utiliza la variable b.
  3. La función outer finaliza su ejecución, y todas sus variables dejan de existir. La variable c deja de existir, aunque la variable b existe como cierre dentro de inner.
var Y= outer(); // outer() invoked the second time
  1. La variable b se crea de nuevo y se establece en 10
    La variable c se crea de nuevo.
    Nota que aunque outer() se ejecutó una vez antes de que las variables b y c dejaran de existir, una vez que la función terminó de ejecutarse se crean como variables completamente nuevas.
    Llamemos a estas b(second_time) y c(second_time) para nuestra propia referencia.
  2. La función inner es devuelta y asignada a Y
    En este punto la variable b está encerrada dentro de la cadena de alcance de la función inner como un cierre con b(second_time)=10, ya que inner utiliza la variable b.
  3. La función outer finaliza su ejecución, y todas sus variables dejan de existir.
    La variable c(second_time) deja de existir, aunque la variable b(second_time) existe como cierre dentro de inner.

Ahora veamos qué ocurre cuando se ejecutan las siguientes líneas de código:

X(); // X() invoked the first time
X(); // X() invoked the second time
X(); // X() invoked the third timeY(); // Y() invoked the first time

Cuando se invoca X() por primera vez,

  1. se crea la variable a, y se establece en 20
  2. el valor de a=20, el valor de b es del valor de cierre. b(first_time), por lo que b=10
  3. las variables a y b se incrementan en 1.
  4. X() completa la ejecución y todas sus variables internas – la variable a – dejan de existir.
    Sin embargo, b(first_time) se conservó como cierre, por lo que b(first_time) sigue existiendo.

Cuando se invoca X() por segunda vez,

  1. la variable a se crea de nuevo, y se establece como 20
    Cualquier valor anterior de la variable a ya no existe, ya que dejó de existir cuando X() terminó de ejecutarse la primera vez.
  2. El valor de a=20
    el valor de b se toma del valor de cierre – b(first_time)
    También hay que tener en cuenta que habíamos incrementado el valor de b en 1 desde la ejecución anterior, por lo que b=11
  3. las variables a y b se incrementan en 1 de nuevo
  4. X() completa la ejecución y todas sus variables internas -la variable a- dejan de existir
    Sin embargo, b(first_time) se conserva ya que el cierre sigue existiendo.

Cuando se invoca X() por tercera vez,

  1. la variable a se crea de nuevo, y se establece como 20
    Cualquier valor anterior de la variable a ya no existe, ya que dejó de existir cuando X() terminó de ejecutarse la primera vez.
  2. El valor de a=20, el valor de b es del valor de cierre – b(first_time)
    También hay que tener en cuenta que habíamos incrementado el valor de b en 1 en la ejecución anterior, por lo que b=12
  3. Las variables a y b se incrementan en 1 de nuevo

  4. X() completa la ejecución, y todas sus variables internas – la variable a – dejan de existir
    Sin embargo, b(first_time) se conserva ya que el cierre sigue existiendo
  5. Cuando se invoca Y() por primera vez,

    1. la variable a se crea de nuevo, y se establece en 20
    2. el valor de a=20, el valor de b es del valor de cierre – b(second_time), por lo que b=10
    3. las variables a y b se incrementan en 1
    4. Y() completa la ejecución, y todas sus variables internas – la variable a – dejan de existir
      Sin embargo, b(second_time) se conservó como cierre, por lo que b(second_time) sigue existiendo.

    Observaciones finales

    Los cierres son uno de esos conceptos sutiles en JavaScript que son difíciles de entender al principio. Pero una vez que los entiendes, te das cuenta de que las cosas no podían ser de otra manera.

    ¡Espero que estas explicaciones paso a paso te hayan ayudado a entender realmente el concepto de cierres en JavaScript!

    Otros artículos:

  • Una guía rápida de funciones «autoinvocables» en Javascript
  • Entendiendo el ámbito de la función vs. el ámbito del bloque en Javascript
  • Cómo usar promesas en JavaScript
  • Cómo construir una sencilla animación Sprite en JavaScript

.

Navegación de entradas

Aric Almirola y Smithfield amplían su contrato con Stewart-Haas Racing
¿Qué es el blackface?

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Entradas recientes

  • Firebush (Español)
  • 9 mejores vitaminas y suplementos para perros para mejorar su salud
  • Previsión de tasas de CD para 2021: Las tasas probablemente se mantendrán bajas, pero podrían aumentar más adelante en el año
  • Dolor pélvico crónico y prostatitis: síntomas, diagnóstico y tratamiento
  • Juegos y actividades saludables para niños | UIC Online Informatics
  • Cervezas de trigo (americanas)
  • Los beneficios de la lactancia materna después de un año
  • ¿Es seguro tirar los posos del café por el fregadero?
  • Enfriarse después de hacer ejercicio
  • Nuestro trabajo

Meta

  • Acceder
  • Feed de entradas
  • Feed de comentarios
  • WordPress.org

Archivos

  • marzo 2021
  • febrero 2021
  • enero 2021
  • diciembre 2020
  • DeutschDeutsch
  • NederlandsNederlands
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • PolskiPolski
  • 日本語日本語
©2021 Info Cafe | WordPress Theme by SuperbThemes.com