一、js的运行三部曲
1,语法分析:简单来说就是通篇扫描一遍,看看有没有语法错误;
2,预编译:预编译发生再执行的前一刻,会做两件事情,(1)函数声明整体提升(2)变量 声明提升
3,解释执行:js有两个特性,单线程和解释性语言,啥叫解释性语言,简单来说就是解释一句执行一句
二、预编译
1,imply global 暗示全局变量:即任何变量,如果没有经过声明就赋值,此变量就为全局所有
function test(){
c = 123;//c未经声明就赋值,此时c就为全局变量,可以通过window.c访问到
var a = b = 123;//先将123赋值给b,发现b没有声明,此时b就为全局变量,可以通过window.b访问到
}
console.log(c);//123
console.log(b);//123
2,一切申明的全局变量全是window的属性
var a = 123; ===> window.a = 123;
console.log(a);//123
console.log(window.a);//123
函数预编译四部曲:
1,创建AO (Activation Object)对象,就是执行期上下文
2,找形参和变量声明,将变量和刑参作为AO对象的属性,值为undefined
3,将实参值和刑参的值统一
4,在函数体里面找函数声明,将函数名作为AO对象的属性值挂起来,值赋予函数体
全局预编译:
1,创建GO (Global Object === window)对象,就是执行期上下文
2,找变量声明,将变量作为AO对象的属性,值为undefined
3,在函数体里面找函数声明,将函数名作为AO对象的属性值挂起来,值赋予函数体
function test(a){
console.log(a);
var a = 123;
console.log(a);
function a () {}
console.log(a);
var b = function () {}
console.log(b);
function d (){}
}
test();
//首先创建AO 对象 AO{}
// 然后找刑参和变量声明,将变量和刑参作为AO对象的属性,值为undefined
// AO {
// a:undefined,
// b:undefined,
// }
//再将实参和刑参的值统一
// AO {
// a:1,
// b:undefined
// }
//在函数体里面找函数申明,将函数名作为AO对象的属性值挂起来,值赋予函数体
// AO {
// a:function a () {}, 此时同命的a被覆盖
// b:undefined,
// d:function d () {}
// }
//此时AO对象已经创建完毕,预编译结束,开始执行函数(预编译发生在函数执行的前一刻),AO对象就是我们所说的作用域
//代码执行过程分析:
//第一行代码开始执行,console.log(a);找AO对象拿值,输出function a(){}
//第二行代码var a = 123;开始执行,var a在预编译期间已经执行,此时实际上相当于执行 a = 123;此时AO对象的a的值已经变为123
//第三行代码执行,console.log(a);找AO对象拿值,输出123
//第四行代码,function a(){},预编译期间已经执行,跳过
//第五行代码,console.log(a);找AO对象拿值,输出123
//第六行代码,执行,AO属性的b的值为function () {}
//第七行代码,console.log(b);找AO对象拿值,输出funcion (){}
//第八行代码预编译期间已经执行,跳过
//函数执行完,AO对象变为
// AO {
// a:123, 此时同命的a被覆盖
// b:function () {},
// d:function d () {}
// }