execution context
- GO AO 都属于 execution context,是在函数执行期前一刻生成的。包含函数的变量声明、函数声明等。
- 在函数执行期间,如果产生赋值等操作依旧会执行期上下文里的值产生影响。
GO
- global execution context
- 存储 this--window window--object document--object 及其他初始值和引用值
AO
- function or constructor function execution context
- function() AO 存储 this--window arguments--[] 及其他初始值和引用值
- new Function() AO 存储 this--{} arguments--[] 及其他初始值和引用值
编译的前置条件
- 函数只有执行前才会进行编译
- 函数如果只有定义,没有执行,函数体内的变量不会对外界产生影响。
编译步骤
- 寻找变量声明和参数定义
- 实参赋值给形参
- 寻找函数声明,并赋值函数体
- 函数执行赋值
es5 不允许在{}块级作用域中声明函数。但es5浏览器为了兼容旧的代码没有遵循这一规定,在{}中依旧可以声明函数并提升函数体至全局或函数作用域顶部。
补充
-
如果函数内声明了与全局变量名字相同的变量,全局变量对函数内的变量不会产生影响。如下:
- 声明变量时,如果未使用var声明变量,如直接a = 1,则a不存在变量提升。
-
if &&等逻辑判断不会阻断预编译上下文。如下:
- return 语句为表达式,相当于赋值语句,不参与预编译的变量提升。
// 示例1:
function a(){
console.log(b);
return function b(){} // 相当于函数表达式 x = function b(){}
}
var bb = a();
bb(); // 报错,b is not defined
// 示例2:和题目关系不大,此处说明闭包的问题,多个闭包拥有的是同一份环境的AO。
function a(){
var a = 1;
return a = function(){
console.log(a);
a = 2;
}
}
var bb = a();
bb(); // function(){}
bb(); // 2
-
函数执行时,如果有全局变量,会把全局变量及变量的值一起挂载到全局中。但是函数编译时,不会对全局变量产生影响。如下:
actual combat
- 分析下面程序的GO、AO及打印正确的结果
a = 1;
function test(e){
function e(){}
arguments[0] = 2;
console.log(e);
if(a){
var b = 3;
}
var c;
a = 4;
var a;
console.log(b);
f = 5;
console.log(c);
console.log(a);
}
var a;
test(1);
//分析过程
GO = {
a: undefined,
1,
}
AO = {
b: undefined,
c: undefined,
a: undefined,
4,
e: undefined,
1,
function e(){},
2,
}
//执行结果 2 undefined undefined 4


