当大厂面试官问你js预编译时,你又该如何应对

110 阅读2分钟

当JavaScript中的变量声明提升和预编译过程成为你的得力帮手

在JavaScript开发中,理解变量声明提升和预编译过程是非常重要的。本文将深入剖析var、let和const关键字的声明提升规则,并介绍编译器在函数体内和全局环境下的工作原理。

声明提升

var关键字

使用var关键字声明的变量存在声明提升。在代码执行前阶段,变量声明会被移动到作用域的顶部,但赋值操作保留在原来的位置。例如:

console.log(myVar); // 输出:undefined
var myVar = 5;

实际上,上面的代码在执行时相当于以下形式:

var myVar;
console.log(myVar);
myVar = 5;

函数声明整体提升

与var类似,函数声明也会整体提升至作用域的顶部。例如:

myFunc(); // 可以正常调用
function myFunc() {
  console.log("Hello, world!");
}

let关键字

使用let声明的变量不会存在声明提升,并且不能重复声明同一变量。

const关键字

使用const声明的变量也不会存在声明提升,同时不允许重复声明同一变量,并且声明后不允许修改其值。

编译器的工作原理

函数体内的预编译

  1. 创建函数的AO对象(Action Object);
  2. 找形参和变量声明,将形参和变量声明作为AO的属性名,值赋予undefined
  3. 将形参和实参统一;
  4. 在函数体内找到函数声明,将函数名作为AO对象的属性名,值赋予函数体。

全局预编译

  1. 创建一个GO对象(Global Object);
  2. 找变量声明,将变量声明作为GO对象的属性名,值赋予undefined
  3. 在全局找到函数声明,将函数名作为GO对象的属性名,值赋予函数体。

如图

image.png

//在执行之前会进行编译,首先,创建一个GO对象
GO = {
    //找变量声明,值赋予undefined,找函数声明,值赋予函数体
    global : undefined,
    fn : function fn() {},
}
//然后执行
GO = {
    global : 100,//执行赋值语句 global = 100
    fn : function fn() {},
}
//发现函数fn()的调用,先对其进行编译,首先,创建一个AO对象
AO = {
    global : undefined,//因为没有形参和函数声明,所以AO对象中只有这一个属性,且值为undefined
}
//然后执行console.log(global),由上面可知,输出为undefined
AO = {
    global : 200,//然后执行赋值语句 global = 200
}
//继续执行console.(global),输出为200
AO = {
    global : 300,//然后执行赋值语句 global = 300
}

所以最终的输出结果为 undefined 200

通过深入理解这些概念,你可以更好地掌握JavaScript代码执行的规律,避免意外行为,提高代码的可读性和可维护性。

希望本文对您有所帮助,也欢迎大家分享更多关于JavaScript预编译和变量提升的知识。