Articles

Cómo funcionan los cierres de JavaScript, en inglés sencillo

JavaScript es un lenguaje ampliamente adoptado que puedes utilizar para construir cualquier cosa, desde una simple página de aterrizaje hasta una aplicación de producción completa. A medida que JavaScript y la programación en general evolucionaron, los desarrolladores se dieron cuenta de que el paradigma de la programación orientada a objetos (POO) es indeseable para la mayoría de los casos de uso. La programación funcional surgió como la solución a muchos de los puntos de dolor asociados con la POO.

Los cierres son un tema ampliamente discutido en el mundo de la programación funcional, pero a menudo se definen de forma imprecisa y en la jerga técnica. Haremos todo lo posible aquí para explicar cómo funcionan los cierres de JavaScript en términos de lenguaje sencillo.

Al final de este tutorial, deberías entender:

  • Cómo identificar los cierres
  • Qué es un cierre y cómo se comporta en relación con el contexto de ejecución y la pila de llamadas
  • Casos de uso comunes para los cierres

Entendiendo los cierres de JavaScript

Empezaremos mostrando cómo es un cierre.

Intenta ejecutar el código por tu cuenta. Técnicamente, la función llamada makeCounter devuelve otra función llamada increment. Esta función increment tiene acceso a la variable count incluso después de que se haya ejecutado la función makeCount. Parte del cierre aquí es la variable count; está disponible para la función increment cuando se define, incluso después de que makeCounter termine. La otra parte es la función increment.

Imagina que tienes una casa y un jardín que la rodea. Una vez que abres la puerta del jardín y la cierras, no puedes volver a abrirla: el jardín queda inaccesible. Tienes hambre y, afortunadamente, hay un naranjo y un manzano en tu jardín. Coges una pequeña bolsa, arrancas una naranja y una manzana y vuelves a entrar en tu casa. Recuerda que no puedes volver a salir.

Ahora, una vez que estás dentro de tu casa, puedes sacar la naranja o la manzana de la bolsa y comerla cuando vuelvas a tener hambre. La bolsa pequeña en este ejemplo es el cierre. Un cierre contiene todas las variables y funciones que estaban a tu disposición cuando estabas en el jardín, incluso cuando estás dentro de la casa y no puedes volver a salir.

Veamos cómo se desarrolla esto en el código:

Como la variable fruits está disponible para la función devuelta cuando se ejecuta makeFruitGarden, la variable fruits y la función interna se convierten en el cierre. Cada vez que se ejecuta consumeFruit, se devuelve un fruit – el último elemento del array fruits porque se está utilizando pop(). Una vez que ambas frutas han sido consumidas/comidas, no quedará nada que comer.

Entendiendo el ámbito léxico

Para entender realmente los cierres, debes estar familiarizado con el término «ámbito». El ámbito léxico es un término elegante para el entorno actual relativo a lo que sea que se refiera.

En el siguiente ejemplo, el ámbito de la variable llamada myName se llama «ámbito global».

// global scopeconst myName = "John Doe"function displayName() { // local/function scope console.log(myName);};displayName()

Puede que hayas visto este concepto referenciado al leer cómo var no tiene ámbito de bloque y cómo constlet sí. Es importante tener en cuenta que en JavaScript, una función siempre crea su propio ámbito. Esto se llama el ámbito local o function, como se muestra en el ejemplo de código.

Si has estado prestando atención, podrías estar pensando que myName y displayName son parte de un cierre. Estarías en lo cierto. Pero como la función y la variable aquí existen en el ámbito global, no tiene mucho valor llamarlo cierre.

Hay muchos tipos de ámbitos en JavaScript, pero cuando se trata de cierres, hay tres ámbitos que debes conocer:

  1. El ámbito global es el ámbito por defecto donde viven todos. Piensa en él como tu calle
  2. El ámbito externo de la función es la función que devuelve una función. Tiene su propio ámbito. Piensa en él como tu jardín
  3. El ámbito de la función interna/local es la función devuelta que se convierte en un cierre. Piensa en ello como tu casa
  4. Ahora vamos a sumergirnos en algunos casos de uso.

    Casos de uso comunes para cierres

    Currying

    El currying de funciones es otro concepto poderoso en la programación funcional. Para implementar una función curry en JavaScript, se utilizarían closures.

    Currying una función puede describirse como la transformación de una función y se ejecuta así: add(1, 2, 3) a add(1)(2)(3).

    function add(a) { return function(b) { return function(c) { return a + b + c; }; };};add(1)(2)(3) // returns 6

    La función add toma un solo argumento y luego devuelve dos funciones que se anidan una tras otra. El objetivo del currying es tomar un montón de argumentos y finalmente terminar con un único valor.

    Funciones de orden superior

    El objetivo de una función de orden superior es tomar una función como argumento y devolver un resultado. Los métodos de array como map y reduce son ejemplos de funciones de orden superior.

    const arrayOfNumbers = ;const displayNumber = (num) => { console.log(num);}arrayOfNumbers.forEach(displayNumber)

    La función de orden superior Array.prototype.forEach aquí acepta displayNumber como argumento y luego la ejecuta para cada elemento en el arrayOfNumbers. Si has utilizado un framework de interfaz de usuario como Vue o React, puede que estés familiarizado con los componentes de orden superior, que son esencialmente lo mismo que las funciones de orden superior.

    Entonces, ¿cuál es la diferencia entre las funciones de orden superior y el currying? Mientras que una función de orden superior toma una función como argumento y devuelve un valor, una función de curry devuelve una función como resultado, lo que finalmente lleva a un valor.

    Administradores de elementos DOM

    Este es un patrón de diseño común que se utiliza a menudo para obtener y establecer propiedades de elementos DOM. En el siguiente ejemplo, haremos un gestor de elementos para estilizar elementos.

    makeStyleManager devuelve un objeto que da acceso a dos funciones, que forman parte de un cierre junto a las variables element y currentStyles. Incluso después de que makeStyleManager haya terminado de ejecutarse, las funciones getStyle y setStyle tienen acceso a las variables.

    Conclusión

    Los cierres de JavaScript pueden ser difíciles de entender, incluso para desarrolladores con experiencia profesional a sus espaldas. Entender los cierres acabará por convertirte en un mejor desarrollador.

    Ahora deberías ser capaz de identificar un cierre cuando se está utilizando en una base de código que parece extraña o no tiene sentido. Los cierres son un concepto crítico en la programación funcional y espero que esta guía te haya ayudado a dar un paso adelante en tu viaje hacia su dominio.

    LogRocket: Depura los errores de JavaScript más fácilmente entendiendo el contexto

    Depurar código es siempre una tarea tediosa. Pero cuanto más entiendas tus errores más fácil será solucionarlos.

    LogRocket te permite entender estos errores de formas nuevas y únicas. Nuestra solución de monitorización del frontend rastrea el compromiso del usuario con sus frontends de JavaScript para darle la capacidad de averiguar exactamente lo que el usuario hizo que condujo a un error.

    LogRocket registra los registros de la consola, los tiempos de carga de la página, los stacktraces, las solicitudes/respuestas de red lentas con cabeceras + cuerpos, los metadatos del navegador y los registros personalizados. Entender el impacto de su código JavaScript nunca será más fácil!

    Pruébalo gratis.

    Más lecturas

  • «Nunca entendí los cierres de JavaScript» – Una guía técnica y en profundidad para entender cómo funciona un cierre. Ideal para alguien que quiera entender los cierres con respecto a la ExecutionContext, la pila de llamadas, el entorno léxico, etc.
  • Referencia MDN para los cierres de JavaScript – Una guía de referencia rápida para los cierres (incluyendo algunos errores comunes) en caso de que necesites repasar tu memoria rápidamente
  • «Domina la entrevista de JavaScript: ¿Qué es un cierre?» – Los cierres explicados por Eric Elliot; ideal para los desarrolladores que tienen una comprensión de los conceptos de programación funcional

Dejar una respuesta

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