大厂深层拷问——详剖JS中预编译的深层处理

325 阅读3分钟

前言:

对于引擎本身拿到代码该如何处理,执行出运算结果?不妨今天就深层次的来解答引擎是如何进行预编译的。

在预编译阶段,JavaScript引擎会做以下几件事情:

  1. 创建作用域链:JavaScript中的作用域是通过作用域链来实现的,预编译阶段会创建作用域链,确定变量和函数的作用域关系。
  2. 提升变量声明:JavaScript中的变量声明(使用var关键字)和函数声明会被提升到当前作用域的顶部。这意味着在预编译阶段,变量和函数的声明会被提升到作用域的顶部,但初始化(赋值)部分不会被提升。
  3. 函数声明优先:在预编译阶段,函数声明会被提升到作用域的顶部,并且在变量声明之前。这意味着无论函数声明在代码中的位置如何,都可以在声明之前调用这些函数。
  4. 变量声明提升:变量声明也会被提升到作用域的顶部,但初始化部分不会提升。变量的初始化是在代码执行阶段进行的。

作用域链: 作用域是执行期上下文对象的集合,这种集合呈链式连接,我们把这种链式关系称之为作用域链。

简单来说:预编译就是代码在执行前需要进行编译操作,用于确定代码之间的各种关联

正文:

引擎是如何先编译在执行编译器上的代码?

方法:

发生在全局作用域

  1. 创建GO对象
  2. 找变量声明,将变量名作为GO的属性名,值为undefined
  3. 在全局找函数声明,将函数名作为GO的属性名,值为该函数体

发生在函数体内作用域:

  1. 创建一个AO对象
  2. 找形参和变量声明,将形参和变量名作为AO的属性名,值为undefined
  3. 形参和实参统一
  4. 在函数体内找函数声明,将函数名作为AO的属性名,值为该函数体
    function fn(a) {
    console.log(a);
    var a = 123
    console.log(a);
    function a() {} //
    console.log(a);
    var b = function() {}
    console.log(b);
    function c() {}
    var c = a
    console.log(c);   
}

fn(1)

首先

  1. 在全局作用域内创造GO对象
  2. 找变量声明:这段代码并没有
  3. 函数声明:
GO:{
     fn: function () {}
 }

在编译完全局作用域内后执行全局作用域,引擎就来到了fn()函数的调用。

其次 4. 函数作用域内创建一个AO对象 5. 找形参和变量声明,将形参和变量名作为AO的属性名,值为undefined

AO:{
     a: undefined    
     b: undefined    
     c: undefined    
 }
  1. 形参和实参统一
  AO:{
     a: undefined    1
     b: undefined    
     c: undefined    
 }
  1. 在函数体内找函数声明,将函数名作为AO的属性名,值为该函数体
AO:{
     a: undefined    1  function
     b: undefined    
     c: undefined    function
 }

到此预编译结束 ,进行代码执行。

最终结果:

function fn(a) {
    console.log(a);//function
    var a = 123
    console.log(a);//123
    function a() {} //
    console.log(a);//123
    var b = function() {}
    console.log(b);//function
    function c() {}
    var c = a
    console.log(c);   //123
}

fn(1)

//  AO:{
//      a: undefined    1  function    123
//      b: undefined    function
//      c: undefined    function   123
//  }

image.png

最终在终端结果运行正确。

完美解答:

var global = 100

function fn() {
    console.log(global);
}

fn()

这道题该如何解释?

及格解答: 因为函数体内找不到global,跳到外层作用域找,找到global 的值为100。

这个解答是正确的,但并不能让大厂面试官认为你深刻了解。而我之前介绍的方法站在引擎的角度彻底来剖析解答,很好的解决了。看看大家的解答...