Comprensión profunda de la elevación de declaraciones de JavaScript

¡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 varvariables y functionfunciones 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 aa través varde , esta declaración var ase 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

functionLa 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 varlas 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 lety constno 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.logantes , fooes 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.
    foo(); // 200
    var foo = 100;
    function foo() {
        console.log(200);
    }
    复制代码
    El código anterior es equivalente a:
    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 undefineda (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
复制代码

Referencia en este artículo

Supongo que te gusta

Origin juejin.im/post/7085328890788315150
Recomendado
Clasificación