var foo = "hello"; var c = (function a () {function b () {var bar = "world"; alert (foo + bar); return bar;} return b;}) () (); alert (foo + c);Este ejemplo aparece Hello World dos veces;
1. ¿Qué es un cierre?
La explicación "oficial" es: el llamado "cierre" se refiere a una expresión (generalmente una función) que tiene muchas variables y un entorno unido a estas variables, por lo que estas variables también son parte de la expresión.
Creo que pocas personas pueden entender directamente esta oración porque la describió demasiado académicamente. Quiero usar cómo crear un cierre en JavaScript para decirle qué es un cierre, porque es muy difícil comprender directamente la definición de un cierre saltando el proceso de creación de cierre. Mira el siguiente código:
función a () {var i = 0; función b () {alerta (++ i);} return b;} var c = a (); c ();Este código tiene dos características:
1. La función B está anidada interna de la función A;
2. Función A Devuelve la función b.
De esta manera, después de ejecutar var c = a (), la variable C en realidad apunta a la función b. Después de ejecutar C (), aparecerá una ventana para mostrar el valor de I (la primera vez es 1). Este código en realidad crea un cierre. ¿Por qué? Porque la función externa variable C se refiere a la función B interna A, es decir,:
Cuando la función interna B de la función A está referenciada por una variable externa A, se crea un cierre.
Supongo que todavía no entiendes los cierres porque no sabes qué los cierres tienen. Sigamos explorando a continuación.
2. ¿Cuál es la función de los cierres?
En resumen, la función de un cierre es que después de que A se ejecuta y devuelve, el cierre hace que el mecanismo de recolección de basura de JavaScript GC no recupere los recursos ocupados por A, porque la ejecución de una función interna B de A necesita confiar en las variables en a. Esta es una descripción muy directa del papel de los cierres, que no es profesional o riguroso, pero significa aproximadamente que lo es. Comprender los cierres requiere un proceso gradual.
En el ejemplo anterior, después de que se devuelve la función A, siempre existe, por lo que cada vez que se ejecuta C (), I es el valor de I alertado después de agregar 1.
Entonces imaginemos otra situación. Si A devuelve no la función B, la situación es completamente diferente. Porque después de que A se ejecuta, B no se devuelve al mundo exterior de A, sino que solo se hace referencia por A, y en este momento A solo será referenciado por B, por lo que las funciones A y B son referenciadas entre sí, pero no son perturbadas por el mundo exterior (referido por el mundo exterior), las funciones A y B serán recicladas por GC. (El mecanismo de recolección de basura de JavaScript se introducirá en detalle más adelante)
3. El mundo microscópico en el cierre
Si queremos tener una comprensión más profunda de la relación entre los cierres y la función A y la función anidada B, necesitamos introducir varios otros conceptos: el entorno de ejecución de la función (contexto de excución), el objeto activo (objeto de llamada), el alcance (alcance) y la cadena de alcance. Tome el proceso de función A de definición a ejecución como ejemplo para ilustrar estos conceptos.
1. Al definir la función A, el intérprete JS establecerá la cadena de alcance de la función A en el "entorno" donde A se encuentra al definir a. Si A es una función global, solo hay objetos de ventana en la cadena de alcance.
2. Cuando se ejecuta la función A, A ingresará al entorno de ejecución correspondiente (contexto de excitación).
3. En el proceso de crear un entorno de ejecución, A primero agregará un atributo de alcance, es decir, el alcance de a, y su valor es la cadena de alcance en el paso 1. Es decir, la cadena de alcance de A.scope = a.
4. El entorno de ejecución creará un objeto activo (objeto de llamada). El objeto activo también es un objeto con atributos, pero no tiene un prototipo y no se puede acceder directamente a través del código JavaScript. Después de crear el objeto activo, agregue el objeto activo a la parte superior de la cadena de alcance de a. En este momento, la cadena de alcance de A contiene dos objetos: el objeto activo de A y el objeto de la ventana.
5. El siguiente paso es agregar un atributo de argumentos al objeto activo, que guarda los parámetros pasados al llamar a la función a.
6. Finalmente, agregue todos los parámetros formales de la función A y las referencias a la función interna B al objeto activo de a. En este paso, la definición de la función B se completa, por lo que en el paso 3, la cadena de alcance de la función B se establece en el entorno definido por B, es decir, el alcance de A.
En este punto, toda la función A se completa de la definición a la ejecución. En este momento, A devuelve una referencia a la función B a C, y la cadena de alcance de la función B contiene una referencia al objeto activo de la función A, es decir, B puede acceder a todas las variables y funciones definidas en a. La función B se hace referencia por C, y la función B se basa en la función A, por lo que la función A no será reciclada por GC después de que se devuelva.
Cuando se ejecuta la función B, también será lo mismo que el anterior. Por lo tanto, la cadena de alcance de B durante la ejecución contiene 3 objetos: el objeto activo de B, el objeto activo de A y el objeto de la ventana, como se muestra en la figura a continuación:
Como se muestra en la figura, al acceder a una variable en la función B, la orden de búsqueda es buscar primero su propio objeto activo, y si existe, volverá. Si no existe, continuará buscando el objeto activo de la función A, y buscará a su vez hasta que se encuentre. Si no se puede encontrar en toda la cadena de alcance, se devuelve indefinido. Si hay un objeto prototipo prototipo para la función B, luego, después de buscar su propio objeto activo, primero busque su propio objeto prototipo y luego continúe buscando. Este es el mecanismo de búsqueda variable en JavaScript.
4. Escenarios de aplicación de cierres
1. Proteja la seguridad de las variables en la función. Tomando el primer ejemplo como ejemplo, en la función A, solo se puede acceder por la función B, pero no se puede acceder a través de otros canales, protegiendo así la seguridad de I.
2. Mantenga una variable en la memoria. Aún así, debido al cierre, en función siempre existe en la memoria, por lo que cada vez que se ejecuta c (), me agregarán 1.
Los dos puntos anteriores son los escenarios de aplicación más básicos para los cierres, y muchos casos clásicos se originan a partir de esto.
5. Mecanismo de recolección de basura de JavaScript
En JavaScript, si un objeto ya no se hace referencia, el objeto será reciclado por GC. Si se hace referencia a dos objetos y ya no son referenciados por la tercera persona, los dos objetos a los que se hace referencia entre sí se reciclarán. Debido a que la función A está referenciada por B, B es referenciada por C fuera de A, por lo que la función A no se reciclará después de la ejecución.
El artículo anterior comprende de manera integral que el mecanismo de cierre es todo el contenido que comparto con usted. Espero que pueda darle una referencia y espero que pueda apoyar más a Wulin.com.