js预编译主要分为两种
一、全局预编译
思考一下这段代码在控制台输出什么?
console.log(a)
var a = 1
function a(){}
console.log(a)
像这种全局预编译我们只需要记住4个步骤:
1.创建全局活动对象VO
2.将变量声明作为活动对象的键且将其值赋值为undefined
3.寻找函数声明将函数名作为活动对象的键且值为函数本身,如果函数名和变量名重复则函数名覆盖变量名,值也会变成函数本身
4.预编译完成之后再执行script代码
console.log(a)
var a = 1
function a(){}
console.log(a)
//根据以上步骤
//1.创建活动对象VO
//2.将变量声明作为VO的键,并且值为undefined,此时VO:{a:undefined}
//3.寻找函数声明,这里function a(){}会覆盖之前VO对象中的a,此时VO:{a: f a(){}}
//4.执行代码第一个console.log(a)输出f a(){},然后又将a赋值为1,最后第二个console.log(a)输出 1
//最终浏览器输出的结果为 f a(){} 1
二、函数预编译
function a(b,c){
console.log(b)
var b = 0
console.log(b)
var b = function(){
console.log('bbb')
}
console.log(c)
console.log(b)
}
a(1)
这是一个经典的函数预编译过程,思考一下这段代码在控制台输出什么?
这种函数预编译我们首先要明白一个概念:函数是在被执行的时候才会有预编译过程,这里第一行只是一个函数声明,第11行才是真正的执行函数,然后我们要知道函数预编译的步骤。
1.函数被执行时创建变量对象AO(active object)
2.寻找函数中的变量声明作为变量AO的键,值为undefined
3.将形参作为变量对象AO的键,值为undefined,如果与变量重名,则直接覆盖就行
4.将实参的值赋值给形参,此时AO对象中某些以形参为键的值会因实参的赋值而发生变化
5.寻找函数声明作为变量对象AO的键值为undefined
6.执行函数
function a(b,c){
console.log(b)
var b = 0
console.log(b)
var b = function(){
console.log('bbb')
}
console.log(c)
console.log(b)
}
a(1)
//函数预编译 注意:是在函数执行的时候进行函数的预编译
//1.创建变量对象Ao:{}
//2.寻找变量声明作为Ao的键Ao:{b:undefined}
//3.形参作为变量对象AO的键Ao:{b:undefined,c:undefined}
//4.将实参的值赋值给形参Ao:{b:1,c:undefined}
//5.寻找函数声明作为Ao的键,值为undefined 这里没有函数声明 Ao:{b:1,c:undefined}
//6.函数执行 依次输出 1,0,undefined,f(){console.log('bbb')}
最后留给大家一个小练习题,试一下下面这段代码输出的是什么吧!
function fn(a,c){
console.log(a)
var a = 123
console.log(a)
console.log(c)
function a(){}
if(false){
var d = 678
}
console.log(d)
console.log(b)
var b = function(){}
console.log(b)
function c(){}
console.log(c)
}
fn(1,2)