Prefacio: sigue siendo un artículo introductorio. Hay varias características de lenguaje muy importantes en JavaScript: objetos, herencia prototipo y cierres. Entre ellos, los cierres son una nueva característica de lenguaje para los programadores que usan el lenguaje estático tradicional C/C ++. Este artículo comenzará con ejemplos para introducir las características del lenguaje de los cierres de JavaScript y combinar algunas especificaciones de lenguaje de ECMAScript para permitir a los lectores comprender los cierres más profundamente.
Nota: Este artículo es un artículo introductorio, y los materiales de ejemplo se compilan en Internet. Si es un maestro, puede presentar sugerencias y opiniones técnicas sobre el artículo. Este artículo analiza JavaScript, y no desea comparar idiomas. Si está naturalmente incomodado con JavaScript, tome un desvío.
¿Qué es un cierre?
¿Qué es un cierre? El cierre es el cierre, que es una nueva característica que los idiomas estáticos no tienen. Pero los cierres no son algo tan complicado que son incomprensibles. En resumen, los cierres son:
Los cierres son el conjunto de variables locales de la función, pero estas variables locales continuarán existiendo después de que la función regrese.
Los cierres son la "pila" de la función y no se liberan después de que la función regresa. También podemos entender que estas pilas de funciones no están asignadas en la pila, sino que se asignan en el montón.
Al definir otra función dentro de una función, se generará un cierre
La segunda definición anterior es la primera descripción complementaria, que extrae el objeto de predicción de sujeto de la primera definición: el cierre es un conjunto de 'variables locales' de la función. Es solo que se puede acceder a esta variable local después de que regresa la función. (Esta no es una definición oficial, pero esta definición debería ser más propicio para su comprensión de los cierres)
Como variables locales, el código puede acceder a ellas en la función, y no hay diferencia entre este lenguaje estático. La diferencia entre los cierres es que las variables locales aún se pueden acceder por código fuera de la función después de ejecutar la función. Esto significa que la función debe devolver una "referencia" al cierre, o asignar esta "referencia" a una variable externa para garantizar que las variables locales en el cierre se accedan por código externo. Por supuesto, la entidad que contiene esta referencia debe ser un objeto, porque en JavaScript, todos los demás, excepto los tipos básicos, son objetos. Desafortunadamente, ECMAScript no proporciona miembros y métodos relevantes para acceder a variables locales en el cierre. Sin embargo, en ECMAScript, la función interna definida en el objeto de función es una variable local que puede acceder directamente a las funciones externas. A través de este mecanismo, podemos completar el acceso al cierre de la siguiente manera.
La copia del código es la siguiente:
FUNCIÓN AUDADO (Nombre) {
var text = 'Hola' + nombre; // variable local
// Cada vez que se genera un cierre, y el objeto de función interna se devuelve a la persona que llama
Función de retorno () {alerta (texto); }
}
var sayshello = saludo ("cierre");
sayshello () // Acceda al texto variable local a través del cierre
El resultado de la ejecución del código anterior es: Hello Cierre, porque después de ejecutar la función de saludo, la función sayhello () aún puede acceder al texto variable local definido dentro de él.
Ok, este es el efecto del cierre legendario. Los cierres tienen muchos escenarios y modos de aplicación en JavaScript, como Singleton, Power Constructor y otros modos de JavaScript que son inseparables del uso de cierres.
Modelo de cierre de ECMAScript
¿Cómo implementa los cierres de ECMAScript? Si desea tener una comprensión profunda, puede obtener las especificaciones de ECMAScript para la investigación. Solo daré una explicación simple aquí, y el contenido también proviene de Internet.
Cuando se ejecuta la función del script EcMascript, cada asociación de funciones tiene un escenario de contexto de ejecución (contexto de ejecución), que contiene tres partes.
El medio ambiente
El ambiente variable
Esta encuadernación
El tercer punto de este vinculación no tiene nada que ver con los cierres y no se discute en este artículo. Un identificador variable utilizado en el entorno gramatical para analizar el proceso de ejecución de funciones. Podemos pensar en un entorno gramatical como un objeto que contiene dos componentes importantes, el registro del entorno (entorno recodificador) y una referencia externa (puntero). El registro de entorno contiene variables locales y variables de parámetros declaradas internamente por la función, y la referencia externa apunta al escenario de ejecución de contexto del objeto de función externa. Este valor de referencia es nulo en el escenario de contexto global. Dicha estructura de datos forma una lista vinculada unidireccional, cada una de referencia apunta al escenario de contexto externo.
Por ejemplo, el modelo de cierre en nuestro ejemplo anterior debe ser así. La función Sayhello está en el nivel más bajo, el nivel superior es el saludo de la función y el nivel más externo es la escena global. Como se muestra en la figura a continuación: por lo tanto, cuando se llama a Sayshello, Sayshello encontrará el valor del texto variable local a través de la escena de contexto, por lo que el entorno variable de "cierre de saludo" (el entorno variable) y el entorno gramatical son básicamente el mismo. Para diferencias específicas, consulte el documento de especificación de ECMAScript.
Muestra de columna de cierres
En el artículo anterior, entiendo aproximadamente qué es el cierre de JavaScript y cómo se implementan los cierres en JavaScript. A continuación, lo ayudaremos a comprender los cierres más profundamente apuntando a algunos ejemplos. Hay 5 ejemplos a continuación, y los ejemplos son de los cierres de JavaScript para Dummies (Mirror). Ejemplo 1: las variables locales en los cierres son referencias en lugar de copias
La copia del código es la siguiente:
función dice667 () {
// variable local que termina dentro del cierre
var num = 666;
var saysAlert = function () {alerta (num); }
num ++;
regresar Saysalert;
}
var saysalert = say667 ();
sayalert ()
Por lo tanto, el resultado de ejecución debe aparecer 667 en lugar de 666.
Ejemplo 2: múltiples funciones unen el mismo cierre porque se definen dentro de la misma función.
La copia del código es la siguiente:
function setUpSomeGlObals () {
// variable local que termina dentro del cierre
var num = 666;
// almacenar algunas referencias a las funciones como variables globales
galertNumber = function () {alerta (num); }
ginCreasEnumber = function () {num ++; }
gsetNumber = function (x) {num = x; }
}
setUpSomeGlObals (); // Asignar valores a tres variables globales
GalertNumber (); // 666
ginceasenumber ();
GalertNumber (); // 667
gsetNumber (12); //
GalertNumber (); // 12
Ejemplo 3: Al asignar funciones en un bucle, estas funciones unirán el mismo cierre
La copia del código es la siguiente:
function buildList (list) {
resultado var = [];
for (var i = 0; i <list.length; i ++) {
var item = 'item' + list [i];
result.push (function () {alert (elemento + '' + list [i])});
}
resultado de retorno;
}
function testList () {
var fnlist = buildList ([1,2,3]);
// Uso de j solo para ayudar a prevenir la confusión - podría usar i
para (var j = 0; j <fnlist.length; j ++) {
fnlist [j] ();
}
}
El resultado de la ejecución de TestList es que la ventana indefinida de item3 aparece tres veces, porque estas tres funciones unen el mismo cierre, y el valor del elemento es el último resultado calculado, pero cuando sale del bucle, el valor I es 4, por lo que el resultado de la lista [4] está incendido.
Ejemplo 4: Todas las variables locales de funciones externas están en el cierre, incluso si esta variable se declara después de la definición de función interna.
La copia del código es la siguiente:
función saysalice () {
var saysalert = function () {alert (Alice); }
// variable local que termina dentro del cierre
var alice = 'Hola Alice';
regresar Saysalert;
}
var helloalice = sayalice ();
helloalice ();
El resultado de la ejecución es una ventana con ventana emergente "Hola Alice". Incluso si la variable local se declara después de que la función dice que la variable local, aún se puede acceder a la variable local.
Ejemplo 5: Crea un nuevo cierre cada vez que se llama a la función
La copia del código es la siguiente:
function NewClosure (Somenum, Someref) {
// variables locales que terminan dentro del cierre
var num = somenum;
var anArray = [1,2,3];
var ref = someref;
Función de retorno (x) {
num += x;
anarray.push (num);
alerta ('num:' + num +
'/nanArray' + anArray.ToString () +
'/nref.somevar' + ref.somevar);
}
}
cierre1 = newclosure (40, {someVar: 'cierre 1'});
cierre2 = newclosure (1000, {someVar: 'cierre 2'});
cierre1 (5); // NUM: 45 ANArray [1,2,3,45] Ref: 'SomeVar Closure1'
cierre2 (-10); // num: 990 anarray [1,2,3,990] Ref: 'SomeVar Closure2'
Aplicación de cierres
Singleton Single Piece:
La copia del código es la siguiente:
var singleton = function () {
var privateVariable;
Función PrivateFunction (x) {
... Variable privada ...
}
devolver {
FirstMethod: function (a, b) {
... Variable privada ...
},
SecondMethod: function (c) {
... privatefunction () ...
}
};
} ();
Esta sola pieza se logra a través de un cierre. La encapsulación de miembros y métodos privados se completa a través de cierres. La función principal anónima devuelve un objeto. El objeto contiene dos métodos, el método 1 puede usar variables privadas y el método 2 puede acceder a funciones privadas internas. La cosa a tener en cuenta es el '()' donde termina la función principal anónima. Sin esto '()', no se puede producir una sola pieza. Porque las funciones anónimas solo pueden devolver objetos únicos y no se pueden llamar a otro lugar. Este es el método de usar cierres para generar piezas individuales.