Una función de estado y su entorno (entorno léxico, referencia de entorno léxico ) agrupados (o la función está rodeada por una referencia), tal combinación es el cierre ( cierre ). En otras palabras, el cierre le permite acceder al alcance de la función externa en una función interna. En JavaScript, siempre que se crea una función, el cierre se crea al mismo tiempo que se crea la función.
function foo() {
var i = 0;
return function(){
i++;
console.log(i);
};
}
const bar = foo();
const bar2 = foo();
bar(); //1
bar(); //2
bar2() //1
bar2() //2
bar() // 3
bar2() // 3
Alcance léxico
Mire el siguiente código:
function init() {
var name = "Mozilla"; // name 是一个被 init 创建的局部变量
function displayName() { // displayName() 是内部函数,一个闭包
alert(name); // 使用了父函数中声明的变量
}
displayName();
}
init();
init()
Creó una variable local name
y una displayName()
función nombrada . displayName()
Es init()
una función interna definida en y solo está disponible en el init()
cuerpo de la función. Tenga en cuenta que displayName()
no existe una variable local propia. Sin embargo, debido a que puede acceder a las variables de la función externa, displayName()
puede usar init()
las variables declaradas en la función padre name
.
Después de ejecutar el código usando este enlace JSFiddle , descubrí que displayName()
la alert()
declaración en la función mostraba con éxito name
el valor de la variable (la variable se declaró en su función principal). Este ejemplo de alcance léxico describe cómo el analizador resuelve nombres de variables en el caso de funciones anidadas. El término léxico se refiere al hecho de que el alcance léxico determina dónde está disponible la variable en función de dónde se declara la variable en el código fuente. Las funciones anidadas pueden acceder a las variables declaradas en su ámbito externo.
Cierre
Ahora considere el siguiente ejemplo:
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
El efecto de ejecutar este código es init()
exactamente el mismo que en el ejemplo de función anterior . La diferencia (e interesante) es que la función interna regresa de la función externa displayName()
antes de la ejecución .
A primera vista, puede que no sea intuitivo ver que este código se puede ejecutar con normalidad. En algunos lenguajes de programación, las variables locales en una función solo existen durante la ejecución de la función. Una vez que makeFunc()
se completa la ejecución, puede pensar que la name
variable ya no será accesible. Sin embargo, debido a que el código aún se ejecuta como se esperaba, la situación es claramente diferente en JavaScript.
La razón es que funciona en cierres de formularios JavaScript. Un cierre es una combinación de una función y el entorno léxico en el que se declara la función. El entorno contiene las variables locales que estaban dentro del alcance cuando se creó el cierre. En este ejemplo, myFunc
es una referencia a makeFunc
una displayName
instancia de función creada durante la ejecución . displayName
La instancia de mantiene una referencia a su entorno léxico name
en el que existe la variable . Por lo tanto, cuando se myFunc
llama, la variable name
todavía está disponible y Mozilla
se le pasa su valor alert
.
Aquí hay un ejemplo más interesante: una makeAdder
función:
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
En este ejemplo, hemos definido una makeAdder(x)
función que acepta un parámetro x
y devuelve una nueva función. La función devuelta acepta un parámetro y
y devuelve x+y
el valor.
Esencialmente, makeAdder
es una fábrica de funciones: crea una función que suma y suma el valor especificado y sus parámetros. En el ejemplo anterior, usamos la fábrica de funciones para crear dos nuevas funciones: una suma sus parámetros a 5 y la otra a 10.
add5
add10
Ambos y son cierres. Comparten la misma definición de función, pero guardan diferentes entornos léxicos. En add5
el medio ambiente, x
es 5. En el add10
medio, x
son 10.
Hay algunos hoyos en el cierre.
referencia:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures