预编译:
JS引擎处理脚本的过程。
1.预编译过程
2.执行过程
脚本:
1.创建全局对象GO(windows)上下文
2. 加载脚本文件
3. 预编译
3.1找出所有的变量声明,按照变量名加入全局对象GO,如果已存在,忽略。
3.2找出所有的函数声明,按照函数名加入全局对象,如果存在同名变量或者函数,替换。
3.3非声明的变量和函数不用管。
1.如果遇到没有var的变量,都不是变量声明,全部都认为是windows的全局变量,不参与预编译
console.log(aa);//这里报错,你找他要一个变量,它在windows上找了一遍,发现没有,报错
aa = 5;
console.log(aa);//这里有找到了
2.即使aa在函数中,aa也是全局变量,是运行时生效,不是预编译时生效
console.log(aa);//这里报错,找不到这个变量,
test();//尾部定义函数,头部调用,不会报错
console.log(aa);//这里可以找到的
function test(){
console.log('hello');
aa = 5;
}
console.log(aa);
3.脚本中,所有的变量声明,在脚本的预编译阶段完成,所有的变量声明与实际书写位置无关
console.log(a);//undefined这里不报错,预编译
var a = 5;
console.log(a);//5
4.脚本中,所有的函数声明,在脚本的预编译阶段完成,所有函数的声明与实际书写的位置无关
console.log(f);//没有报错,
function f(){
console.log('hello');
}
5.脚本中,如果变量与函数同名,那么函数将覆盖变量
console.log(f);//这里预编译,函数覆盖这个变量,输出这个函数
var f = 123;
console.log(f);//这里输出123,预编译阶段完成后执行,又给f变量赋值了一个123
function f(){
console.log('hello');
}
6.脚本中,如果变量与函数同名,函数可以覆盖变量,但是变量无法覆盖函数
console.log(f);//这里显示的是函数
function f(){
console.log('hello');
}
var f = 123;
7.脚本中,如果有多个函数同名,那么最后声明的函数将覆盖所有的前面所有的同名函数声明,
并且参数的个数是忽略的,也就是js根本就不支持重载
console.log(f);//输出第二个函数,
function f(x){
console.log('hello1');
}
function f(y){
console.log('hello2');
}
预编译函数的调用
1.创建活动对象AO(Active Object) 上下文
2.预编译:
2.1:scope chain 作用域链
2.2:初始化 argments
2.3:初始化形参,将argments中的值赋值给形参
2.4:找出所有的变量声明,按照变量加入AO ,如果存在,忽略
2.5:找出所有的函数声明,按照函数名加入AO,存在则替换
2.6:this初始化
3.解释执行;
1.函数中,所有变量声明,在函数的预编译阶段完成,所有的变量声明与实际的书写位置无关,
function f(){
console.log(a);//undefined
var a = 25;
console.log(a);//25
}
f();
2.函数中,所有函数声明,在函数的预编译阶段完成,所有的函数声明与实际的书写位置无关、
function f(){
console.log(fin);//可以输出函数
function fin(){
console.log('hello');
}
}
f();
3.函数中,如果变量与函数同名,那么函数将覆盖变量
function f(){
console.log(fin);//返回函数
var fin = 123;
console.log(fin);//返回123
function fin(){
console.log('hello');
}
}
f();
4.函数中,只有函数能够覆盖变量,变量无法覆盖函数
function f(){
console.log(fin);//返回函数
function fin(){
console.log('hello');
}
var fin = 123;
console.log(fin);//返回123
}
f();
5.函数中,后面的函数声明会覆盖前面的函数声明
function f(){
console.log(fin);//输出第二个函数
function fin(x){
console.log('hello1');
}
function fin(x){
console.log('hello2');
}
}
f();
6.函数预编译后,遇到需要访问的变量或者函数,优先考虑自己ao中定义的变量和函数,如果找不到,才会在其定义的上一层ao中寻找,直至到Go,再找不到就报错
var scope = 'global';
function f(){
console.log(1,scope);//undefined
var scope = 'local';
console.log(2,scope);//local
}
f();
console.log(3,scope);//gloabl
上代码执行过程如下
Go.scope -> undefined
GO.f -> function()
Go.scope -> global
GO.f -> function()
Go.scope -> global
GO.f -> function()
f.AO.scope -> undefined
Go.scope -> global
GO.f -> function()
f.AO.scope -> local