El cierre (closure) es una de las grandes dificultades de JavaScript y también su característica distintiva. Muchas aplicaciones avanzadas dependen de los cierres para implementarse.
1. Ámbito de variables
Para entender los cierres, primero hay que entender el especial ámbito de variables de JavaScript.
El ámbito de las variables no es más que dos tipos: variables globales y variables locales.
La particularidad del lenguaje JavaScript es que: dentro de una función se pueden leer directamente las variables globales, pero fuera de la función no se pueden leer las variables locales de la función.
Puntos a tener en cuenta:Al declarar variables dentro de una función, asegúrate de usar el comando var. Si no lo haces, ¡en realidad estás declarando una variable global!
2. ¿Cómo leer desde fuera las variables locales dentro de una función?
Por diversas razones, a veces necesitamos obtener las variables locales dentro de una función. Pero, como se dijo anteriormente, ¡en circunstancias normales esto no es posible! Solo se puede lograr mediante métodos alternativos.
Eso es definir otra función dentro de la función.
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
En el código anterior, la función f2 está incluida dentro de la función f1; en este caso, todas las variables locales dentro de f1 son visibles para f2. Pero al revés no funciona: las variables locales dentro de f2 no son visibles para f1.
Esta es la estructura de "ámbito en cadena" (chain scope) característica del lenguaje JavaScript,
Los objetos hijos buscan hacia arriba, nivel por nivel, las variables de todos los objetos padre. Por lo tanto, todas las variables del objeto padre son visibles para el objeto hijo, pero no a la inversa.
Dado que f2 puede leer las variables locales de f1, ¡entonces si usamos f2 como valor de retorno, podemos leer las variables internas de f1 desde fuera de f1!
3. Concepto de cierre
La función f2 en el código anterior es un cierre.
Las definiciones de cierre en la literatura especializada son muy abstractas. Mi entendimiento es: un cierre es una función que puede leer las variables internas de otras funciones.
Dado que en JavaScript solo las subfunciones dentro de una función pueden leer las variables locales, un cierre puede entenderse simplemente como "una función definida dentro de otra función".
Por lo tanto, en esencia, un cierre es un puente que conecta el interior de una función con el exterior.
4. Usos del cierre
Los cierres se pueden usar en muchos lugares. Sus dos mayores usos son: uno, como se mencionó antes, pueden leer las variables dentro de la función; el otro, hacer que los valores de estas variables se mantengan siempre en la memoria y no se eliminen automáticamente después de que se llame a f1.
¿Por qué sucede esto? La razón es que f1 es la función padre de f2, y f2 se asigna a una variable global, lo que hace que f2 permanezca siempre en la memoria. Como la existencia de f2 depende de f1, f1 también permanece siempre en la memoria y no es recolectada por el mecanismo de recolección de basura (garbage collection) después de finalizar la llamada.
Otro punto digno de atención en este código es"nAdd=function(){n+=1}"Esta línea: primero, no se usa la palabra clave var antes de nAdd, por lo tanto nAdd es una variable global, no una variable local. Segundo, el valor de nAdd es una función anónima (anonymous function), y esta función anónima en sí misma también es un cierre, por lo que nAdd equivale a un setter que puede operar sobre las variables locales dentro de la función desde fuera de la función.
5. Puntos a tener en cuenta al usar cierres
- (1) Dado que los cierres hacen que todas las variables de la función se mantengan en la memoria, el consumo de memoria es grande, por lo que no se deben usar en exceso los cierres; de lo contrario, causarán problemas de rendimiento en la página web y pueden provocar fugas de memoria en IE. La solución es eliminar todas las variables locales que no se utilicen antes de salir de la función.
- (2) Los cierres pueden cambiar el valor de las variables internas de la función padre desde fuera de la función padre. Por lo tanto, si usas la función padre como un objeto (object), el cierre como su método público (Public Method) y las variables internas como sus propiedades privadas (private value), debes tener cuidado de no cambiar arbitrariamente el valor de las variables internas de la función padre.
Enlace original: https://www.cnblogs.com/cxying93/p/6103375.html