Piedra angular de front-end: mecanismo de preprocesamiento, promoción variable

¡Acostúmbrate a escribir juntos! Este es el cuarto día de mi participación en el "Nuevo plan diario de los Nuggets·Desafío de actualización de abril", haz clic para ver los detalles del evento .

promoción variable

En el "contexto actual", antes de que se ejecute el código, el navegador primero declarará y definirá todas las palabras clave con var/función por adelantado. Si var se declara por adelantado, la función no solo se declarará por adelantado sino que también se definirá por adelantado ( asignación).

P.ej:

console.log(a);
var a = 1;
console.log(fn);
function fn() {}
复制代码

La declaración y la definición de a se encuentran después de console.log(a), pero el uso de a por adelantado no reportará un error sino que dará como resultado undefined, lo que indica que a se ha declarado por adelantado .

La declaración y definición de fn están después de console.log(fn), pero si fn se usa por adelantado, no se informará ningún error y fn se emite correctamente, lo que indica que fn no solo se declara por adelantado, sino que también se define (se asigna ) por adelantado .

Promoción variable, independientemente de que la condición sea cierta o no, se realizará la promoción variable. Sin embargo, en el cuerpo del juicio, el rendimiento de las funciones en los navegadores antiguos y nuevos no es el mismo (var no tiene ningún efecto). Declarará y no definirá.

Nueva versión del navegador:

Navegadores de versiones anteriores:

Promoción variable de clase para let y const

¿Por qué let y const promueven variables de clase, porque let y const no tienen promoción de variables, pero tienen algún mecanismo para tratar con let y const?

Tomemos let como ejemplo:

console.log(a);
let a = 1;
复制代码

Dado que let no tiene un mecanismo de promoción variable, definitivamente informará un error si se usa antes de declararlo, pero ¿qué error informará? "Error de referencia no capturado: a no está definido" ?

其实不然,报错 「Uncaught ReferenceError: Cannot access 'a' before initialization」

注意:如果你要在浏览器控制台中直接运行,请加上一个块级作用域。

{
    console.log(a);
    let a = 1;
}
复制代码

这是为什么了?其实最开始浏览器从服务器获取的js都是文本(字符串),声明的文件格式「content-type: application/javascript」。浏览器首先按照这个格式去解析代码,也就是进行「词法解析」生成 AST 语法树。

基于 let、const 等声明的变量,在词法解析阶段就已经明确在此上下文中未来一定会存在这些 let、const 声明的变量,在代码执行时,如果在具体声明的变量之前使用了这些变量,浏览器就会报错 「Uncaught ReferenceError: Cannot access 'a' before initialization」。所以说 let 、const 类似会有一种变量提升,但是本质上并不是变量提升。

看如下代码,用 debugger 看看。

debugger;
console.log(a);
var a = 1;
console.log(b);
let b = 2;
复制代码

发现 b 是定义在脚本中,这里的脚本就是 VG(G),而 a 是在 全局 GO 中,说明二者并不是一样的处理,let 词法解析阶段就已经明确在此上下文中未来一定会存在这些 let、const 声明的变量。

接下来我们看一个面试练习。

面试练习

console.log(fn);
function fn() {
  console.log(1);
}
console.log(fn);
var fn = 12;
console.log(fn);
function fn(){
  console.log(2);
}
console.log(fn);
复制代码

第一步变量提升

  1. function fn() {console.log(1);} fn 函数声明加定义,一个函数的创建会在 Heap 堆内存中开辟一块空间(0x001)来存储函数(详情看上一篇文章:函数的底层执行机制),所以 fn -> 0x001。

  1. var fn = 12; var solo declarará que no se definirá, pero se encuentra que se ha declarado fn en el contexto, por lo que no se repetirá.
  2. function fn(){console.log(2);}, fn ahora es una nueva función, pero se encuentra que fn ya existe en este contexto, por lo que no se repetirá, sino que se redefinirá. Así que abra un nuevo espacio de memoria (0x002) para almacenar la nueva función fn. En comparación con la dirección de memoria fn del primer paso, la apertura de nueva memoria es una operación definida, por lo que fn -> 0x002.

Ejecución de código de segundo paso

  1. console.log(fn); Busque fn en este contexto, se encontró que existe, fn -> 0x002. Entonces salida ƒ fn(){console.log(2);}
  2. se omite la función fn() {console.log(1);} porque este paso ya se maneja en la fase de promoción variable.
  3. console.log(fn); Busque fn en este contexto, se encontró que existe, fn -> 0x002. Entonces salida ƒ fn(){console.log(2);}
  4. var fn = 12; La declaración de var ya fue manejada en la fase de izado de variables, ahora toca reasignarla. fn -> 12

  1. console.log(fn); Busque fn en este contexto, se encontró que existe, fn -> 12. Entonces salida 12.
  2. se omite la función fn(){console.log(2);} porque este paso ya se maneja en la fase de promoción variable.
  3. console.log(fn); Busque fn en este contexto, se encontró que existe, fn -> 12. Entonces salida 12.

Resumir

Este tipo de preguntas con mejora variable a menudo aparecerán en las entrevistas, pero muchos estudiantes pensarán que es relativamente simple y a menudo tendrán problemas. Por lo tanto, cuando se encuentre con este tipo de preguntas, debe ser competente en la creación de un mapa cerebral en su cerebro para comprender. las variables en memoria almacenar puntero. De esta forma, los resultados de salida son claros y sin errores.

Supongo que te gusta

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