预编译
在js中,我们首先需要知道代码是如何执行的?它的执行顺序是什么呢?预编译起了什么作用的?今天小编就带着大家来探索一下。
一、预编译是什么呢?
大家的第一反应可能就是提前编译啊,没错,预编译就是提前编译,但是是发生在函数执行的前一刻,预编译完成后,函数才开始执行。
二 、预编译有哪些过程呢?
小编的理解呢,预编译分为四步:
第一步:生成(创建)了一个AO对象(AO对象也就是执行期上下文);
第二步:找形参和变量声明,将变量和形参名作为AO属性名,值为undefined;
第三步:将实参值和形参值统一;
第四步:在函数体里面找函数声明,值赋予函数体。
下面我们来看几个例子:
function fn(a){ // 这里的a是形参
console.log(a);
//此时的结果,是从创建的AO中取值,即打印的结果为function a(){}
var a = 123; // 声明了一个a
//此时AO对象中的a就变成了123;
console.log(a);
// 所以打印的a值为123;
function a(){} // 函数声明
console.log(a);
// 此时打印的a值仍为123
var b = function(){}; // 声明了一个b
//此时AO对象中的b就变成了function(){};
console.log(b);
// 此时打印的b值仍为function(){};
function d(){} // 函数声明
}
fn(1);
分析:
在函数执行的前一刻,预编译开始
第一步:创建一个 AO{}对象
第二步: AO{
a : undefined;
b : undefined;
}
第三步: AO{
a : 1;
b : undefined;
}
第四步: AO{
a :function a(){}
b :undefined;
d : function d(){}
}
看了这个题目,大家是不是会思考全局有没有预编译呢?
当然了,全局也有预编译,但是全局没有参数,所以没有第三步;但是生成的是GO对象。(GO === window)
预编译过程:
第一步:生成(创建)了一个GO对象
第二步:找形参和变量声明,将变量和形参名作为GO属性名,值为undefined;
第三步:在函数体里面找函数声明,值赋予函数体。
下面看个题目,小编带你进一步理解预编译
/*
分析过程:
1、创建GO对象
GO{
b:123
}
*/
function test(){
var a = b = 123;
//相当于var a; a是局部变量;
//b = 123;没有用var关键字声明,所以b是全局变量
console.log(window.a);
console.log(window.b);
}
test();
/*
在函数执行的前一刻,创建一个AO对象:
1.AO{
a : undefined,
}
*/
第二题:
/*代码执行过程:
1. GO{}
2. GO{
test:undefined;
}
3.GO{
test: function test(test){
console.log(test);
var test = 234;
console.log(test);
function test(){}
}
}
*/
console.log(test);
function test(test){
console.log(test);
var test = 234;
console.log(test);
//此时AO中的test变成了234;
function test(){}
}
/*
1. AO{
test:undefined,
}
2. AO{
test:1,
}
3. AO{
test:function test(){},
}
*/
test(1);
//在函数准备执行的时候,预编译开始
var test = 123;