“三 四部曲”带你走进js的预编译世界

预编译

首先,我们来讲一下什么是预编译:
面对代码,我们可以清晰的知道它的运行方式和顺序,但是,计算机不一定能懂。
在js中,有一个v8引擎,它可以形象的拆分为两个部门,“编译部门”和“执行部门”。在执行代码时,引擎会先让“编译部门”把js代码编译成引擎能读得懂的样子,这个过程就叫预编译。
预编译一定发生在代码执行之前(有些地方是 代码执行之时)

预编译的类型

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

函数预编译“四部曲”

  1. 创建一个AO(activation object)对象
  2. 找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为undefined
  3. 将实参和形参统一
  4. 在函数体里找声明,将函数名作为AO对象的属性名,值赋予函数体
  • 示例:
  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 d() {}
      var d = a
      console.log(d); // 123
    }
    fn(1)

第一步:创建AO对象

AO{
}

第二步:找形参和变量声明并赋值undefined

AO{
	a:undefined 
    b:undefined 
    d:undefined
}

第三步:将实参和形参统一

AO{
	a:1 // 1覆盖掉了undefined
    b:undefined 
    d:undefined
}

第四步:找函数声明

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

执行fn函数时,AO的值的变化过程:

 	AO = {
        a:function a() {},
        b:undefined
        d:function d() {}
    }
    --->
    AO = {
        a:123,
        b:undefined
        d:function d() {}
    }
    --->
    AO = {
        a:123,
        b:function() {}
        d:function d() {}
    }

当我们做完这四部曲时,按照代码逐行执行,答案一目了然。

function() {}
123
123
function() {}
123
注意:

这里要知道函数声明和函数表达式的区别。函数声明不等于函数表达式,他们具有不同的形式。其实很容易理解,函数表达式, var b = function(){} 将一个函数赋值给了一个变量构成了一个表达式。function a() {}就是一个函数声明。

全局预编译“三部曲”

  1. 创建一个GO对象(global boject)
  2. 找变量声明,将变量声明作为GO对象的属性名,值赋予undefined
  3. 找全局里的函数声明,将函数名作为GO对象的属性名,值赋予函数体
  • 示例:
	var global = 100
    function foo() {
      console.log(global); // undefined
      global = 200
      console.log(global); // 200
      var global = 300
    }
    foo()

第一步:创建GO对象

GO{
}

第二步:找全局中的变量声明,并赋值为undefined

GO{
	global: undefined 
}

第三步:找函数声明

GO{
	global: undefined 
	fn: function() {}
}

做到这里我们已经把全局作用域找完了,但还有一个函数作用域。用“四部曲”找。
找完应该是:

GO{
	global: undefined 
	fn: function() {}
}
AO: {
    global: undefined 
    }

执行foo函数,AO和GO的变化过程:

GO{
	global: 100 
	fn: function() {}
}
AO: {
    global: undefined 
    }
    
--->

GO{
	global: 100 
	fn: function() {}
}
AO: {
    global: 200
    }
    
--->
GO{
	global: 100 
	fn: function() {}
}
AO: {
    global: 300
    }

在执行到第一个console.log(global);时,有些人会说输出100,因为GO里面的global的值为100,但实际上输出undefined,因为在函数作用域里面就已经找到了global,值为undefined。所以输出的是undefined。

最后结果:

undefined
200

总结

以后遇到关于预编译的相关问题(有些大厂面试题可能问到哟),大家可以按照上面的步骤进行解决,如果大家在遇到的代码里有if语句的话,在预编译阶段先无视他就可。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值