今天在看腾讯课堂,姬成老师的课程,关于预编译和执行上下文讲解的特别详细。让我明白之前一直迷惑的执行上下文顺序。
这点也是面试的时候经常遇到的面试题。
预编译:发生在函数执行的前一刻,局部声明的时候。
预编译过程:
1、创建AO对象;
2、找形参和变量声明,将变量和形参作为AO对象的属性名,值为undefined;
3、将实参和形参统一;
4、在函数体里面找函数声明,值赋予函数体。
例子:
function fn(a) { console.log(a); var a = 123; console.log(a); function a() { }; console.log(a); var b = function () { }; console.log(b); function d() { }; } fn(1);
解析过程:
第一步:创建AO对象:
AO:{
}
第二步:找形参和变量声明,将变量和形参作为AO对象的属性名,值为undefined;
AO : {
a: undefined,
b: undefined,
}
第三步:将实参和形参统一
AO : { a: 1, b: undefined, }
第四部:在函数体里面找函数声明,值赋予函数体
AO : {
a: function a() { },
b: undefined,
d: function d() { },
}
然后开始解析对象,执行上下文:(已经解析的在执行过程中忽略)
function fn(a) { console.log(a); // 取AO对象里面的a: function a() { } var a = 123; // 将AO对象里面的a重新赋值,为123; console.log(a); // 取AO对象里面的a 123 function a() { }; // 忽略 console.log(a); // 123 var b = function () { }; // 将AO对象里面的b重新赋值为 function b() {} console.log(b); // 取AO对象里面的b 为function(){ } function d() { }; } fn(1);
所有的执行上下文的顺序都可以按照这4个步骤进行分步解析。
全局声明:
全局声明的话,声明的是GO对象,GO对象也就是我们说的window;
1、声明GO对象;
2、将参数值赋值给GO对象值。
3、执行
例子:
var global = 100; function fn(){ console.log(global); } fn();
解析:
第一步:创建GO对象
GO:{ }
第二步:将值赋予给GO对象
GO:{ global: undefined, fn: funciton(){ ... } }
全局变量和局部变量都存在同一个变量值的话,取局部变量;
例子:
global = 100; function fn(){ console.log(global); global = 200; console.log(global); var global = 300; } fn(); var global;
解析:
第一步,全局设置了 var global,则变量提升
GO : {
global: undefined,
fn: funciton() { ... }
}
第二步:fn则存在局部变量,则生成AO对象
AO : { global : undefined, }
第三步: 开始解析
global = 100; function fn(){ console.log(global); // AO对象里面含有global,则取AO对象里面的undefined global = 200; // 将AO对象里面的global赋值为200 console.log(global); // 取AO对象里面的global, 为200 var global = 300; }
fn(); var global;