JavaScript 预编译
JavaScript运行三部曲:
1.语法分析:
先全部扫一遍 看有没有语法错误.
2.预编译(执行前一刻) :
函数声明整体提升
变量 声明提升
函数声明整体提升(相当于提升到程序的最前面)
一个变量被声明后,变量声明提升(相当于把变量声明语句放到最前,赋值不变)
JavaScript的函数作用域是指在函数内声明的所有变量在函数体内始终是有定义的,也就是说变量在声明之前已经可用,
所有这种特性称为声明提前(hoisting),即JavaScript函数里的所有声明(只是声明,但不涉及赋值)都被提前到函
数体的顶部,而变量赋值操作留在原来的位置
函数声明整体提升,函数声明语句将会被提升到外部脚本或者外部函数作用域的顶部
声明了一个变量,同时又声明了一个同名函数,则会先执行变量声明提升,再进行函数声明整体提升
注:以上结论并不完全正确,在复杂情况下上述结论会失效
3.解释执行:
(解释一行执行一行)
在预编译发生前的前奏:
1.imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所拥有。
eg:
a = 123;
console.log(a);---->123
因为变量a未经声明就赋值了,所以变量a就为全局变量所拥有,就是归window所拥有。
上面的语句也可以写同于:
a = 123;
console.log(window.a);---->123
2.一切声明的全局变量,全是window的属性。
eg:
var a = 123;---->window.a = 123;
下面就是预编译的重点:
1.创建AO对象
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3.将实参值和形参统一
4.在函数体里面找函数声明,值赋予函数体
下面就以以下例子说明:
function fn(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() {}
}
fn(1);
解题步骤:
1.首先创建AO对象:
AO{
}
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
AO{
a:undefined
b:undefined
d:undefined
}
3.将实参值和形参统一:
AO{
a:1
b:undefined
d:undefined
}
4.4.在函数体里面找函数声明,值赋予函数体
AO{
a:function a () {}
b:function () {}
d:function d () {}
}
function test(a,b) {
console.log(a);-->1
c = 0;
var c;
a = 3;
b = 2;
console.log(b);-->2
function b() {}
function d() {}
console.log(b);-->2
}
test(1);
解题步骤:
1.首先创建AO对象:
AO{
}
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
AO{
a:undefined
b:undefined
c:undefined
}
3.将实参值和形参统一:
AO{
a:1
b:undefined
c:undefined
}
4.4.在函数体里面找函数声明,值赋予函数体
AO{
a:1
b:function b () {}
c:undefined
d:function d () {}
}
关于在有关全局变量下的预编译:
a = 100;
function demo(e) {
function e() {}
arguments[0] = 2;
console.log(e);-->2
if (a) {
var b = 123;
function c(){
}
}
var c;
a = 10;
var a;
console.log(b);-->undefimed
f = 123;
console.log(c);-->undefined,因为在If语句嵌套函数,是语法错误的,所以function c(){}不能执行
console.log(a);-->10
}
var a;
demo(1);
console.log(a);-->100
console.log(f);-->123
关于全局对象。用GO创建:
GO{
}
GO{
a:undefined
demo:undefined
f:undefined
}
GO{
a:100
demo:function () {}
f:123
}
AO{
}
AO{
e:undefined
b:undefined
c:undefined
a:undefined
}
}
}
AO{
e:2
b:undefined
c:undefined
a:undefined
}
AO{
e:2
b:undefined
c:undefined/function c(){}
a:10
}
总结:
预编译的四个步骤很重要
1.创建AO对象
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3.将实参值和形参统一
4.在函数体里面找函数声明,值赋予函数体
预编译(脚本代码块script执行前)
1.找全局变量声明(包括隐式全局变量声明,省略var声明),变量名作全局对象的属性,值为undefined
2.找函数声明,函数名作为全局对象的属性,值为函数引用