1.概念
执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象 (保存函数的作用域)
上文成员(js语法可以直接访问的成员)
下文成员(底层语法访问的成员 仅供js引擎存取) 如[[scopes]]
- 一个执行期上下文定义了一个函数执行时的环境
- 每次调用函数创建的执行上下文不同
- 当函数执行完毕,它所产生的执行上下文被 "销毁"
执行期上下文指的就是函数执行前一刻所产生的AO对象
函数执行环境就是指变量提升函数提升得到的那些AO对象属性
function fn() { }函数多次调用,产生不同的AO对象:
fn(); ---->AO{}
fn(); ---->AO{}
函数执行完毕之后对应的AO对象销毁
[[scopes]] :指的是作用域 保存了运行期上下文的集合
- 函数生成了就会有个属性 [[scopes]] 作用域“数组” (只能引擎使用)
- 函数调用时生成AO的对象就保存在[[scopes]]对象内部的顶层
- 函数在定义/声明时就有[[scopes]] 里面保存的是这个函数上层的AO对象
作用域链:[[scope]]中所保存的执行期上下文对象的集合 集合呈链式连接
2.作用域链
示例1:
function fn(b) {
var a = 20
function fm() {
}
}
//调用一次就有一个AO对象生成
fn(100) //AO{a:20,b:100,fm:}
fn(200) //AO{a:20,b:200,fm:}
如图:
示例2:
function fn() {
var a = 30
function fm() {
var b = 20
console.log(a)
}
fm()
fm()
}
fn()
fn()
如图:
示例3:
function fn(a) {
function fm() {
var b = 20
console.log(a)
}
fm()
fm()
}
fn(100)
fn(200)
如图:
示例4:
function a() {
function b(){
function c() {
}
c();
}
b();
}
a();
执行的作用域链:
a 定义: a.[[scope]] --> 0:GO
a 执行: a.[[scope]] --> 0:AO(a)
1:GO
b 定义: b.[[scope]] --> 0:AO(a)
1:GO
注意:b执行了才会产生c的定义b 执行: b.[[scope]] --> 0:AO(b)
1:AO(a)
2:GO
c 定义: c.[[scope]] --> 0:AO(b)
1:AO(a)
2:GO
c 执行: c.[[scope]] --> 0:AO(c)
1:AO(b)
2:AO(a)
3:GO
示例5:
function a() {
var aaa = 123;
function b() {
var bbb = 234;
console.log(aaa);
}
return b;
}
var glob = 100;
var demo = a();
demo();
/*
Go:{a函数,glob:100,demo:a.[[scopes对象里面的,b函数]]}
a.[[scopes]]==>[AO:{aaa:123,b函数,},Go]
b函数.[[scopes]]==>[,a.[[scopes]]]<====>[AO(b):{bbb:234,打印aaa},AO(a):{aaa:123,b函数,},Go]
demo()
*/
执行的作用域链:
a 定义: a.[[scope]] --> 0:GO==>{a函数,glob:100,demo:a.[[scopes对象里面的b函数]]}
a 执行: a.[[scope]] --> 0:AO(a)==>{aaa:123,b函数}
1:GO
b 定义: b.[[scope]] --> 0:AO(a)
1:GO
b 执行: b.[[scope]] --> 0:AO(b)==>{bbb:234,打印aaa}
1:AO(a)
2:GO
demo(): GO中找到==>a的作用域==>调用b函数==>b的作用域