首先要明确js执行步骤:
- 检查通篇的语法错误,有语法错误一行都不会执行
- 预编译
- 解释一行执行一行
暗示全局变量 imply global
在全局不管是声明变量也好,不声明变量也好,都会成为window对象的属性
var a = 1;
b = 2; //暗示全局变量
window = {
a: 1,
b: 2
}
函数内未声明的变量也是全局变量
function test() {
var a = b = 1;
}
console.log(a, b) //报错
console.log(window.a, b) //undefined, 1 访问对象里不存在的属性不会报错,只会返回undefined
这个函数体的执行步骤:
- var a
- b = 1,挂载到全局GO
- a = b,局部AO里面没有b,往上去全局找b
预编译
AO(active object)活跃对象/函数上下文
- 创建AO对象
- 寻找函数的形参和变量声明,值为undefined
- 将实参的值赋值给形参
- 寻找函数声明,赋值函数体(不是函数表达式)
- 执行函数
GO(global object)全局上下文 == window
- 创建GO对象
- 找变量
- 找函数声明
- 执行
例1:
var b = 3;
console.log(a); //function a(a) {...}
function a(a) {
console.log(a); //function a() {}
var a = 2;
console.log(a); //2
function a() {};
var b = 5;
console.log(b); //5
}
a(1);
GO = {
a: function a(a) {...}
b: undefined -> 3
}
AO = {
a: undefined -> 1 -> function a() {} -> 2
b: undefined -> 5
}
例2:
a = 1;
function test() {
console.log(a); //undefined,函数内有a,不会到全局里找,AO里的a也提升了
a = 2;
console.log(a); // 2
var a = 3;
console.log(a); //3
}
test();
var a
GO = {
a: undefined -> a
}
AO = {
a: undefined -> 2 -> 3
}
例3:
function test() {
console.log(b); //undefined
if(a) {
var b = 2; //预编译的时候要放进去,因为预编译的时候不看语句,只看有没有变量声明
}
c = 3;
console.log(c); //3
}
var a;
test(); //执行的时候a = undefined,所以函数里面的if语句不执行,b = undefined
a = 1;
console.log(a); //1
GO = {
a: undefined
test: function test() {}
c: 3
}
AO = {
b: undefined
}