作用域
# 作用域
# 预编译
预编译特征
- 任何没有声明的变量直接赋值,那么这个变量将直接归 window 所有。 暗示全局
- 全局声明的变量 会直接归属到 window 下
预编译流程:
- 创建 AO 对象 (AO --> 函数执行期上下文)
- 找形参和变量声明,将变量和形参名作为 AO 属性名,值为 undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体。
预编译决定了函数将要运行时声明的状态(var、function)
function test(a,b){
console.log(a) // function a(){}
var a;
console.log(b) // 2
function a(){}
a = 234;
console.log(a); // 234
var b =123;
console.log(c); // Refference Error c is not define
}
test(1,2);
如果预编译放到全局中会形成另一个 GO 对象。 规则相同。
# 作用域
在预编译阶段会创建出 AO 和 GO (Action Object、Global Object)这叫做函数执行期上下文。发生在函数即将执行之前,如果多次执行一个函数,就会创建多个函数执行期上下文。 [[Scope]] 即作用域,里面存储了执行期的上下文 作用域链:[[Scope]] 中所存储的执行期上下文对象的集合,这个集合呈链式链接,
function a() {
var a = 1;
function b() {
var b = 2;
function c() {
var c = 3;
}
c()
}
b()
}
a()
每个函数都可以看做是一个对象
// example a doing
a --> [[Scope]] -->
[
AO -> {
arguments:{},
this: window,
a:1,
b:function (){}
},
GO -> {
window,
document,
a:function (){},
}
]
逐行解析,作用域的在执行期间作用域顶部始终是自己的执行上下文,
a-- > define-- > [[Scope]]-- > [0: GO]
a-- > doing-- > [[Scope]]-- > [0: a - AO, 1: GO]
b-- > define-- > [[Scope]]-- > [0: a - AO, 1: GO]
b-- > doing-- > [[Scope]]-- > [0: b - AO, 1: a - AO, 2: GO]
c-- > define-- > [[Scope]]-- > [0: b - AO, 1: a - AO, 2: GO]
c-- > doing-- > [[Scope]]-- > [0: c - AO, 1: b - AO, 2: a - AO, 3: GO]
当函数执行完毕,会销毁自身的作用域,将自身的顶部作用域出栈回退回 define 阶段 如果函数再次执行将会再次创建执行期上下文。