作用域
作用域指[[scope]]每个js函数都是一个对象,对象中有些属性我们可以访问但有些不可以,这些属性仅供js引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是我们所说的作用域,作用域里面存储了运行期上下文的集合
作用域链
作用域链指[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,所以我们把这种链式链接叫做作用域链.
运行期上下文
当函数执行时的前一刻(预编译),会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行对应的执行上下文都是独一无二的,(每次执行都会创建一个AO)所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,他所产生的执行上下文被销毁.
function test() {
}
test.[[scope]]
//scope(域)里面存储的是作用域,这个是访问不了的
//每一个对象都有属性有方法
//函数也是一种对象(test.name=test),叫函数类对象
2
3
4
5
6
function a() {
}
var glob = 100;
a();
2
3
4
1.当a函数定义时
a defined-->a.[[scope]]-->0 :GO{}
2.当a函数执行时
创建AO 会放到作用域链的顶端(第 0 位)
a doing-->a.[[scope]]-->0:AO{} 1:GO{}
查找变量:从作用域链的顶端依次向下查找
a会从作用域链的顶端去找 也就是0:AO{}去找
function a() {
function b() {
var bb = 234;
aa = 0;
}
var aa = 123;
b();
console.log(aa)
//输出的是0 因为在b的作用域链b会先找自己的AO
}
var glob = 100;
a();
2
3
4
5
6
7
8
9
10
11
12
a定义时,会有一个a.[[scope]] scope指向的是一个全局的执行上下文GO{} a被执行,会有一个a.[[scope]] scope指向的是最顶端AO{} 下来GO{}
b定义时,用的是a的劳动成果 a的AO{}和GO{} b执行时,会按自己的执行期上下文0.自己的AO 1.A的AO 2.全局的GO 去执行
b函数执行完后需要销毁自己的执行期上下文 b函数执行完也代表a函数执行完了 a函数执行完了也代表b函数没了
# 总结
function a() {
function b() {
function c() {
}
c();
}
b();
}
a();
2
3
4
5
6
7
8
9
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
作用域总结
在任何函数里面想访问变量就找它的作用域链(执行时doing),可以看出在外部的不能访问内部的变量,在里面的可以访问外部的变量,里面所有的aAO都是一个人,bAO都是一个人。
哪个函数先执行完 就销毁哪个