Prefacio
Los cierres son un punto de conocimiento muy importante en el desarrollo de front-end, y definitivamente se preguntarán en la entrevista.
Uno, la definición de cierre
Las referencias a la función y su estado circundante (entorno léxico, entorno léxico) se agrupan para formar un cierre (cierre). En otras palabras, el cierre le permite acceder al alcance de la función externa desde la función interna. En JavaScript, siempre que se crea una función, se genera un cierre cuando se genera la función.
En pocas palabras, un cierre es una función definida en una función .
P.ej:
function Clos(){
var age = 32;
function getNum(){
console.log(age);//32
return age;
}
return getNum;
}
var get_A = Clos();//get_A将会得到Clos()最后的运行返回的结果.即getNum()函数体
get_A();//拿到了变量age的值:32
console.log(age);//报错:ReferenceError: age is not defined
El código anterior getNum()函数
es un cierre , que se define en el cuerpo de la función denominada Clos ().
En segundo lugar, el papel del cierre
Las variables definidas dentro de una función pertenecen a variables locales. El ciclo de vida de una variable local es: cuando se llama a la función en la que se encuentra, se inicia. Una vez ejecutada la llamada, la variable local se liberará. Cuando necesitemos la variable interna de la función, Ha sido puesto en libertad y ya no se puede leer ¿Cómo solucionar este problema en este momento? Tenemos que encontrar una forma de extender su ciclo de vida.
También se puede decir que el propósito del cierre es este, extender el ciclo de vida de las variables locales. Después de que se ejecuta la función, las variables locales no pueden ser liberadas por la memoria, y luego el exterior puede acceder a la variable.
Volvamos al código anterior para analizarlo: el
código se está ejecutando
console.log(age);
El significado original de esta oración es que originalmente queríamos pedir 变量age
salida. Pero el resultado de la compilación informa de un error: la edad no está definida.
Esto se debe a que está 变量age
definido en Clos()函数
, y el alcance está limitado a la función Clos (). 变量age
El equivalente Clos()函数
a la propiedad privada (valor privado).
Entonces, si queremos llamar edad, ¿no hay manera?
En este momento, se refleja el papel del cierre. Clos()函数
El valor de retorno apunta a 闭包函数getNum()
. Debido a que está 闭包函数getNum()
definido en Clos()函数
, podemos usarlo para obtener 变量age
el valor. El cierre es equivalente a un método público (Método público) que se utiliza para proporcionar una interfaz con el mundo exterior para acceder a los datos internos.
Tres, las ventajas y desventajas de los cierres.
Déjame hablar primero de los inconvenientes.
También es debido al mecanismo de cierre que el mecanismo de recolección de basura de JavaScript no recuperará Clos()函数
los recursos ocupados, porque las variables de las que depende la ejecución del cierre están en él. Si hay demasiados cierres en el código, provocará un desbordamiento de la memoria y afectará la carga de la página, así que tenga cuidado al utilizar cierres.
Echemos un vistazo a los beneficios.
Cuando JavaScript está desarrollando proyectos en colaboración con varias personas, si se definen demasiadas variables globales, puede causar conflictos de nombres de variables globales, que pueden resolverse bien mediante el uso de cierres.
//公司程序员小李和小王一起协作开发项目
var name = '小李';//小李定义了一个全局变量
//var name = '小王'; //如果小王继续定义相同名字变量就会覆盖小李写的变量name的值
var private = (function(){
var name ='小王';
function getName() {
return name;
}
return getName;
}());
console.log("小王定义的name:"+private());
console.log("小李定义的name:"+name);
En el código anterior, el primero se var name='小李'
define en el ámbito global de la ventana. El segundo se var name = '小王'
define en el cuerpo funcional, y el alcance no se afecta entre sí, lo que evita la contaminación global.
para resumir
Los cierres tienen principalmente las siguientes características:
-
La función establece funciones, los cierres deben tener funciones anidadas. El propósito del cierre es acceder a las variables locales dentro de la función, si las variables locales no están definidas, no lograremos nuestro propósito, extender el ciclo de vida de la variable.
-
La función externa debe tener una variable local y la función interna debe operar esta variable de la función externa.
-
La función externa debe devolver la función interna al exterior, use return.
Al hacer el problema de cierre, también debemos prestar atención a los siguientes dos puntos:
- Cuando la función externa se llama varias veces, se creará un nuevo alcance, lo que significa que las variables locales de la función externa operada por la función interna no se verán afectadas
- La función interna devuelta por la función externa se llama varias veces, y las variables locales de la función externa operada por la función interna cambiarán varias veces.
//模拟了用户去银行存钱并查询余额的功能
function Person(name){
var money = 0;
function setMoney(m){
money = m;
}
function getMoney(){
return money;
}
return {
name:name,
setMoney:setMoney,
getMoney:getMoney
}
}
//第一次调用
var LiLei = person('李磊');
LiLei.setMoney(4500);//用户李磊存入4500元
//第二次调用
var WangWu = person('王武');
WangWu.setMoney(7000);//用户王武存入7000元
console.log(LiLei.getMoney());//得到并输出账户余额:4500
console.log(WangWu.getMoney());//得到并输出账户余额:7000
var LiLei = person('李磊');
var WangWu = person('王武');
Este código simula el proceso de apertura de una cuenta para dos usuarios diferentes que llaman a una función 变量money
para modificar el valor de la operación . Debido a que cada llamada repetida abrirá un nuevo alcance, el dinero de Li Lei y Wang Wu no se depositará juntos. El dinero de Li Lei y Wang Wu se almacena en dos espacios de memoria diferentes.