何为预编译?
解释何为“预编译”之前先说说JS,众所周知JavaScript是解释型语言,何为解释型语言?也就是编译一行,执行一行。那又从何而来的预编译呢?
先说说JS运行的三个步骤
-
语法分析
-
预编译
-
解释执行
~~语法分析就是字面上的意思,就是检查你的代码有没有什么低级的语法错误,如果有明显的语法错误,就直接报错不执行所有的代码
~~预编译就是在编译内容之前对中的内容进行处理,也就是进行预处理。
~~解释执行顾名思义就是执行代码了
具体想要弄清楚预编译怎么回事,我们先用一个小实例看看
var a = 123;
console.log(a);//123
这个时候输出的值为123
console.log(a);//undefined
var a = 123;
刚刚我们把这两行代码前后调换了位置,得到的结果却是天壤之别,输出的值为undefined。
为何输出的是“undefined”而不是123或者报错呢?
之所以不是输出123,因为定义的变量a在console.log(a)的后面,按着Js解释型语言的特点,解释一行执行一行,console.log(a)便无法检测到a的值,那为何没有报错呢?
这就涉及到我们今天的主角了--“预编译”,正是它的原因我们这段代码在浏览器显示没有报错,这就是预编译的原因
那么我们再深度剖析何为预编译,即预编译的步骤:
初步理解就是把函数声明(function(){})整体提升最前方,变量声明(例:var a)也提升最前方。
此时我们再看之前举出的例子
console.log(a);
var a = 123;
===》预编译的过程就是把全局变量var a提升最前方,就避免了报错
var a
console.log(a);
a = 123;
这种方法简单是简单,但遇见了复杂的代码将无从下手
下面将描述函数中真正正规对待任何函数都有作用的预编译
第一步:
创建AO(ActivationObject)活跃对象:
AO对象用来放置函数中的变量,此时的AO对象没有值
AO = {
}
第二步:
找形参和变量声明 将变量和形参作为AO对象的属性名 值为underfined
例:
AO = {
a:underfined
b:underfined
}
第三步:
将实参值和形参统一
例:
AO = {
a:1;
b:underfined
}
第四步:
在函数体里面找函数声明,值赋予函数体
例:
AO = {
a : function a(){},
b : undefined,
d :function d(){}
}
下面我们把这四个步骤用一个具体的例子带入进去
var a = 1;
console.log(a);// => 1
function test(a) {
console.log(a);// =>function a(){}
var a = 123;
console.log(a);// => 123
function a() {}
console.log(a);// => 123
var b = function() {}
console.log(b);// => function()
function d() {}
}
var c = function (){
console.log("6666");
}
console.log(c);// => function(){console.log("6666")}
test(2);
分析:
先找出GO全局对象GO(Global Object)全局变量
GO = {
a : 1
c : function(){...}
test:function(a){...}
}
在test()之前发生预编译
预编译第一步:
AO = {
}
预编译第二步:
AO = {
a:undefined,
b:undefined,
}
预编译第三步:
AO = {
a:2,
b:undefined,
}
预编译第四步:
AO = {
a:function a() {},
b:undefined
d:function d() {}
}
预编译完成
预编译小结
1.函数声明整体提升 2.变量 声明提升 3.预编译发生在函数执行前的一刻 4.imply global 即任何变量,如果未经声明就赋值,则此变量就位全局变量所有。(例如:a = 7)