js是一门解释性语言,主要特点是一行一行执行代码。
但在js运行前,会先进行预编译,下面我就来说说这个预编译的规则。
首先给大家举个例子:
var a=123;
console.log(a) //123
如果调换下位置
console.log(a); //undefined
var a=123
如果我们不定义变量
console.log(a) //报错
为什么同样打印a,会有这么大的差别,这就是预编译的作用。
首先,先普及一个概念:
- 变量声明 var...
- 函数声明 function...
<script>
var a = 1;// 变量声明
function b(y){//函数声明
var x = 1;
console.log('so easy');
};
var c = function(){//是变量声明而不是函数声明!!
//...
}
b(100);
</script>
- 页面产生边创建GO全局对象(Global Object),也就是window对象
- 第一个脚本文件加载
- 脚本加载完毕后,分析语法是否合法
- 开始预编译
- 查找变量声明,作为GO属性,赋值undefined
- 查找函数声明,作为GO属性,赋值函数体
GO/window = {
//页面加载创建GO同时,创建了document、navigator、screen等等属性,此处省略
a: undefined,
c: undefined,
b: function(y){
var x = 1;
console.log('so easy');
}
}
完成后开始逐行执行代码,直到执行函数b
GO/window = {
//变量随着执行流得到初始化
a: 1,
c: function(){
//...
},
b: function(y){
var x = 1;
console.log('so easy');
}
}
执行函数b;
执行函数b前,也会发生预编译:
- 创建AO活动对象(Active Object)
- 查找形参和变量声明,赋值undefined
- 实参赋值给形参
- 查找函数声明,赋值函数体
//伪代码
AO = {
//创建AO同时,创建了arguments等等属性,此处省略
y: 100,
x: undefined
}
大家要注意,
预编译阶段发生变量声明和函数声明,没有初始化行为(赋值),匿名函数不参与预编译
只有在解释执行阶段才会进行变量初始化