Un cierre es la combinación de una función y el entorno léxico (alcance) dentro del cual se declaró esa función. Los cierres son una propiedad fundamental y poderosa de Javascript. Este artículo analiza el 'cómo' y el 'por qué' sobre los cierres:
El cierre 'recuerda' el entorno en el que fue creado. Este entorno consta de cualquier variable local que estaba dentro del alcance en el momento en que se creó el cierre.
Los cierres son útiles porque le permiten "recordar" datos y luego le permiten operar con esos datos a través de funciones devueltas. Esto permite que javascript emule métodos privados que se encuentran en otros lenguajes de programación. Los métodos privados son útiles para restringir el acceso al código, así como para administrar su espacio de nombres global.
### Variables y métodos privados.
Los cierres también se pueden utilizar para encapsular datos / métodos privados. Echale un vistazo a éste ejemplo:
En este ejemplo, no podremos acceder al `balance` desde cualquier lugar fuera de la función `bankAccount` , lo que significa que acabamos de crear una variable privada. ¿Dónde está el cierre? Bueno, piensa en lo que `bankAccount()` está devolviendo. En realidad, devuelve un Objeto con un montón de funciones dentro de él y, sin embargo, cuando llamamos `account.getBalance()` , la función es capaz de "recordar" su referencia inicial para `balance` . Ese es el poder del cierre, donde una función "recuerda" su alcance léxico (alcance de tiempo de compilación), incluso cuando la función se ejecuta fuera de ese alcance léxico.
**Emulando variables de ámbito de bloque.**
Javascript no tenía un concepto de variables de ámbito de bloque. Lo que significa que cuando se define una variable dentro de un forloop, por ejemplo, esta variable también es visible desde fuera del forloop. Entonces, ¿cómo pueden los cierres ayudarnos a resolver este problema? Vamos a ver.
Dado que la variable i no tiene un ámbito de bloque, su valor dentro de las tres funciones se actualizó con el contador de bucle y creó valores maliciosos. El cierre puede ayudarnos a resolver este problema creando una instantánea del entorno en el que se encontraba la función cuando se creó, preservando su estado.
Las últimas versiones de javascript es6 + tienen una nueva palabra clave llamada let que se puede usar para darle a la variable un blockscope. También hay muchas funciones (forEach) y bibliotecas completas (lodash.js) que están dedicadas a resolver problemas como los explicados anteriormente. Ciertamente pueden aumentar su productividad, sin embargo, sigue siendo extremadamente importante tener conocimiento de todos estos problemas al intentar crear algo grande.
Los cierres tienen muchas aplicaciones especiales que son útiles al crear grandes programas javascript.
1. Emulando variables privadas o encapsulación.
2. Realización de llamadas laterales al servidor asíncrono.
3. Creando una variable de ámbito de bloque.
**Emulando variables privadas.**
A diferencia de muchos otros idiomas, Javascript no tiene un mecanismo que le permita crear variables de instancia encapsuladas dentro de un objeto. Tener variables de instancia pública puede causar muchos problemas al crear programas medianos y grandes. Sin embargo, con los cierres, este problema puede ser mitigado.
Al igual que en el ejemplo anterior, puede crear funciones que devuelvan literales de objetos con métodos que tengan acceso a las variables locales del objeto sin exponerlas. Así, haciéndolos efectivamente privados.
Los cierres también pueden ayudarlo a administrar su espacio de nombres global para evitar colisiones con datos compartidos globalmente. Generalmente, todas las variables globales se comparten entre todos los scripts en su proyecto, lo que definitivamente le dará muchos problemas al crear programas medianos o grandes. Es por eso que los autores de bibliotecas y módulos utilizan cierres para ocultar los métodos y datos de un módulo completo. Esto se denomina patrón del módulo, utiliza una expresión de función invocada de inmediato que exporta solo cierta funcionalidad al mundo exterior, reduciendo significativamente la cantidad de referencias globales.
Aquí hay una breve muestra de un módulo esqueleto.
El patrón de módulo es muy común en JavaScript. Uno de usos más grande es en la biblioteca (Redux). Es una de las bibliotecas más populares para la administración de estado. En la cual cierres previenen leer o escribir fuera de la función dispatch().
Los cierres son útiles para capturar nuevas instancias de variables privadas contenidas en el entorno "recordado", y solo se puede acceder a esas variables a través de la función o los métodos devueltos.