¡Acostúmbrate a escribir juntos! Este es el día 11 de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de abril", haga clic para ver los detalles del evento .
Este artículo fue publicado por primera vez en mi blog .
1. Introducción
El motor JS se precompilará antes de ejecutar JavaScript. Durante la precompilación de JS, las declaraciones de var
variables y function
funciones en JS avanzarán al frente del alcance actual.
Artes tradicionales, primero veamos una pregunta para ver si ha comprendido completamente la promoción de la declaración: ¿cuál
es el resultado correcto del siguiente código? (La respuesta es la mejor, si no lo tienes muy claro, se recomienda seguir leyendo).
var foo = function () {
console.log(100);
}
function foo() {
console.log(200);
}
foo();
复制代码
2. Impulso declarativo
Antes de que el motor JS interprete y ejecute el código, primero procesará todas las declaraciones en cualquier código, incluidas las variables y funciones, y las colocará al frente del alcance actual, mientras que las declaraciones de asignación restantes permanecerán en su lugar y esperarán a que se ejecuten. La declaración se adelanta desde la posición original al frente del ámbito actual, por lo que se denomina elevación de declaración (Hoisting) .
2.1 Declaración de variables de elevación
// 输出 undefined
console.log(a);
var a = 'hello';
复制代码
De acuerdo con la promoción de variables, la variable se declara a
a través var
de , esta declaración var a
se adelantará y la variable a = 'hello'
permanecerá en su lugar. Entonces el código es equivalente a:
var a;
// 输出 undefined
console.log(a);
a = 'hello';
复制代码
Tenga en cuenta que las declaraciones de variables se elevan, pero las inicializaciones de variables no.
// 输出 undefined
console.log(a);
var a;
a = 'hello';
复制代码
Cada ámbito en el código se iza.
console.log(a); // undefined
var a = 100;
function fn() {
console.log(b); // undefined
var b = 200;
function gn() {
console.log(c); // undefined
var c = 300;
}
gn();
}
fn();
复制代码
La salida del código anterior, después de ser impulsado, es equivalente a:
var a;
console.log(a); // undefined
a = 100;
function fn() {
var b;
console.log(b); // undefined
b = 200;
function gn() {
var c;
console.log(c); // undefined
c = 300;
}
gn();
}
fn();
复制代码
2.2 Declaración de funciones de elevación
function
La declaración de una función también tiene la característica de elevación de la declaración, y la declaración de la función (incluido el cuerpo de la función) se coloca al frente del alcance actual.
// 输出 hello
foo();
function foo() {
console.log('hello');
}
复制代码
El código anterior es equivalente a:
function foo() {
console.log('hello');
}
// 输出 hello
foo();
复制代码
Tenga en cuenta que var
las expresiones de función declaradas no tienen elevación de declaración de función. Por ejemplo, la siguiente expresión de función anónima:
// 输出 undefined
console.log(foo);
foo(); //TypeError: foo is not a function
var foo = function () {
console.log('hello');
}
复制代码
El código anterior es equivalente a:
var foo;
console.log(foo); // 输出 undefined
foo(); // TypeError: foo is not a function
foo = function () {
console.log('hello');
};
复制代码
Para las expresiones de función con nombre, tampoco hay declaración de elevación.
console.log(foo); // undefined
foo(); // TypeError: foo is not a function
var foo = function bar() {
console.log('hello');
}
复制代码
Nota: El nombre de una expresión de función con nombre solo se puede usar dentro de la función, no fuera de la función.
var bar = 10;
var foo = function bar() {
bar = 30; // (3)
console.log(bar); // (1)
}
foo();
console.log(bar); // (2)
bar(); // (4)
复制代码
En el código anterior, (1) genera:
ƒ bar() {
bar = 32;
console.log(bar);
}
复制代码
Salida en (2): 10
, el código en (3) no es válido y se informa un error en (4).
Las declaraciones
let
yconst
no tienen la función de elevación de declaraciones.
3. La declaración de funciones tiene prioridad
Si hay declaraciones de variables y funciones con el mismo nombre en el código, ambas se promocionarán y, finalmente, la declaración de la función anulará la declaración de la variable.
// 输出:foo () {}
console.log(foo);
var foo = 100;
function foo () {}
复制代码
El código anterior es equivalente a:
function foo() {};
var foo; // 变量提升被函数声明提升覆盖,变量重复声明无效
console.log(foo); // foo() {}
foo = 100;
复制代码
Pero si hay una declaración de asignación console.log
antes , foo
es el valor de la variable.
var foo = 100;
function foo () {};
console.log(foo); // 100
复制代码
Tenga en cuenta que las declaraciones repetidas de variables son inútiles, pero las declaraciones repetidas de funciones anulan las declaraciones anteriores .
- Las declaraciones repetidas de variables son inútiles
var foo = 100; var foo; console.log(foo); // 100 复制代码
- Las declaraciones duplicadas de funciones sobrescriben las declaraciones anteriores
foo(); // 200 function foo () { console.log(100); } function foo () { console.log(200); } 复制代码
- La declaración de funciones tiene prioridad sobre la declaración de variables.
El código anterior es equivalente a:foo(); // 200 var foo = 100; function foo() { console.log(200); } 复制代码
function foo() { console.log(200); } var foo; foo(); // 200,函数声明提升优先于变量声明提升,变量声明无效 foo = 100; 复制代码
4. Algunos casos
Caso 1:
var bar = 100;
function foo () {
console.log(bar); // (1)
var bar = 200;
console.log(bar); // (2)
}
复制代码
dará salida a (1) y salida undefined
a (2) 200
. Según el principio de promoción variable, el código anterior es equivalente a:
var bar = 100;
function foo () {
var bar;
console.log(bar); // undefined
bar = 200;
console.log(bar); // 200
}
复制代码
Caso 2:
var foo = function () {
console.log(100);
}
function foo() {
console.log(200);
}
foo();
复制代码
El código anterior generará 100
, de acuerdo con el principio de prioridad de promoción de declaración de función , el código se puede convertir a:
function foo() {
console.log(200);
}
var foo;
foo = function () {
console.log(100);
} // 原函数被变量赋值覆盖,此时 foo 函数体为后面赋值的。
foo(); // 100
复制代码