1、[[scope]]:每个JavaScript函数都是一个对象,对象的有些属性我们可以访问,有些不可以,这些属性仅供引擎存取,其中[[scope]]就是其中一个。[[scope]]值得是我们所说的作用域,存储了运行期上下文集合(执行期上下文(AO GO)见https://blog.csdn.net/gxgalaxy/article/details/88729727)。
2、作用域链:[[scope]]中存储的执行期上下文对象的集合,集合呈链式连接,这就叫作用域链。
我们以下面函数为例:
function a(){
function b(){
var b = 234;
}
var a = 123;
b();
}
var glob = 100;
a();
// a defined-->a.[[scope]]-->0:GO{}
// a doing a.[[scope]]-->0:AO{}
// 1:GO{}
当a函数被定义的时候产生全局执行期上下文GO:
当a函数被执行的时候产生自己的执行期上下文AO:这个时候a的AO会放在作用域链的顶端
由于a的执行产生了b函数的定义,b作为一个函数也有自己的[[scope]],当b出生的时候,他的环境是a给的,所以:
b被创建的时候发生的过程:
b在执行的时候,也生成自己的执行期上下文放在作用域链的顶端:
在b中寻找变量的时候,从作用域链的顶端往下找。
该过程中存在的疑问:
1、b执行过程中a的AO是否和a的AO相同:我们采用改变b函数中的aa,再在a中访问aa来判断两者是否相同。
function a(){
function b(){
var bb = 234;
aa = 0;
}
var aa = 123;
b();
console.log(aa);
}
var glob = 100;
a();
运行结果 aa = 0,说明两者是同一个。
2.当a执行完被销毁以后,a回到被执行前,此时b也消失。
例题:
function a(){
function b(){
function c(){
}
c();
}
b();
}
a();
//定义和执行过程中作用域的变化
a defined a.[[scope]]-->0:GO
a doing a.[[scope]]-->0:aAO
1:GO
b defined b.[[scope]]-->0:aAO
1:GO
b doing b.[[scope]]-->0:bAO
1:aAO
2:GO
c defined c.[[scope]]-->0:bAO
1:aAO
2:GO
c doing c.[[scope]]-->0:cAO
1:bAO
2:aAO
3:GO
注意:a函数不执行,b函数也不能被定义。每次执行完都会回到被定义的状态。