Skip to content

Javascript中的预编译

预编译在什么时候发生

预编译分为全局预编译和函数预编译:全局预编译发生在页面加载完成时执行,而函数预编译发生在函数执行的前一刻。

全局预编译的步骤

  1. 创建GO(Global Object,全局执行期上下文,在浏览器中为window)对象;
  2. 寻找var变量声明,并赋值为undefined;
  3. 寻找function函数声明,并赋值为函数体;
  4. 执行代码。

一个小案例

我们先来看一下下面这段代码:

js
var x = 1,
    y = z = 0;

function add (n) {
  return n = n + 1;
}

y = add(x);
function add (n) {
  return n = n + 3;
}

z = add(x)

分析

1.创建一个GO对象

js
const OA={
      //创建一个OA对象
}

2.寻找var变量声明,并赋值为undefined;

js
  var x = undefined
  var y = undefined
  var z = undefined

3.寻找function函数声明,并赋值为函数体

js
function add (n) {
  return n = n + 1;
}  //忽略 因为被下面一个代替了
function add (n) {
  return n = n + 3;
}

4.执行代码

js
x=1
function add (n) {
  return n = n + 3;
} 
y = add(x)
z = add(x)
y= 4
z= 4
   //所以x=1 y=4 z=4

函数预编译的步骤

  1. 创建AO对象,执行期上下文(后面更新关于执行期上下文详解)。
  2. 寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
  3. 将形参和实参相统一,即更改形参后的undefined为具体的形参值。
  4. 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。

一个小案例

js
function fn(a){
    console.log(a);
    var a = 123;
    console.log(a);
    
    function a(){};
    console.log(a);
    
    var b = function(){};
    console.log(b);
    
    function d(){};
 }
 
 //调用函数
 fn(1);

1.创建OA对象

js
const OA={

}

2.寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.

js
  var a=undefined
  var b=undefined

3.将形参和实参相统一,即更改形参后的undefined为具体的形参值

js
AO{
var a = 1
var b = undefined
}

4.寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。

js
AO{
    a: function(){}
    b: undefined
    d: function(){}
}

函数开始逐行顺序执行:

js

function fn(a){
    console.log(a);// 输出function a(){}
    var a = 123;
    console.log(a);// 输出123
    
    function a(){};//预编译环节已经进行了变量提升,故执行时不在看这行代码
    console.log(a);// 输出123
    
    var b = function(){};//这个是函数表达式不是函数声明,故不能提升,会对AO中的b重新赋值
    console.log(b);//输出function(){}
    
    function d(){};
 }