执行期上下文就是AO
互相嵌套的函数,外层的函数不能访问里层函数的东西,里层的能访问外层函数
执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象,一个执行期上下文定义了一个函数执行时的环境(比如:变量提升,函数提升),函数每次执行时对应的执行上下文都是独一无二的,所以多此调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁
查找变量:从作用域链的顶端依次向下查找
一:一个函数每次执行前会创建一个执行期上下文,执行完,会销毁执行上下文,每个函数都有自己的作用域
二:作用域精解:
[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合
[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式连接,我们把这种链式链接叫做作用域链
三:查找变量:从作用域链顶端依次向下执行
AO放在作用域顶端
<!-- 例一 -->
<script>
function a(){
}
var glob=100;
a();
//a 定义 a.[[scope]]-->0: GO{}
//a 执行 a.[[scope]]-->0: AO{} AO放在作用域链的顶端
// 1: GO{}
</script>
例2:在a函数里再定义一个b函数
//执行a函数时开始创建b的作用域链
//b函数被创建时,发生如下过程:它保存的是A的劳动成果,b访问的AO就是a产生的AO
//b的作用域链产生的AO就是a的AO
//b函数被执行时,创建AO,放在最顶端
//当b函数被执行完时,销毁掉自己产生的AO,GO不会被销毁,回到被定义的状态,等到下一次被执行,下次执行时会产生一个新的AO,在原来的基础上
//当a函数被执行完,b没了,a回到被定义时的状态,再执行时,发生同样过程,不再赘述了
它们的GO是同一个
<!-- 例二 -->
<script>
function a(){
function b(){
var b=234;
}
var a=123;
b();
}
var glob=100;
a();
</script>
a函数被定义时,发生如下过程: a函数被执行时,发生如下过程:
b函数被创建时: b函数被执行时:
b的aAO和a的AO是同一个,只是借用
<!-- 例三 -->
<script>
function a(){
function b(){
function c(){
}
c();
}
b();
}
a();
//这就是为什么里面的函数能访问到外面的函数,而外面的函数却访问不到里面的函数的原因 b的AO只有a和b的,c的有abc的
// a 定义:a.[[scope]]-->0:GO
// a 执行:a.[[scope]]-->0:aAO
// 1:GO
// a的执行产生一个b定义:
// b 定义: b.[[scope]]-->0:aAO
// 1:GO
// b 执行: b.[[scope]]--> 0:bAO
// 1:aAO
// 2:GO
// c定义: c.[[scope]]--> 0:bAO
// 1:aAO
// 2:GO
// c执行: c.[[scope]]--> 0:cAO
// 1:bAO
// 2: aAO
// 3:GO
</script>
<!-- 例5 -->
<script>
function a(){
function b(){
var bbb=234;
console.log(aaa);
}
var aaa=124;
return b;
}
var glob=100;
var demo=a();//a执行的结果保存到demo里了,b保存进来了
//但凡是内部的函数被保留到了外部,一定生成闭包
demo();
</script>
例5图:
例6
<script> function a(){ var num=100; function b(){//b继承了a的AO和GO num++; console.log(num); } // 如果这里使b(),b执行,形成不了闭包,把b函数返回出去才形成闭包 return b;//返回函数b 生成了闭包 } var demo=a();//这里外部空间存了b,因为把b return出去了,b的AO什么也没生成,里面没有num,去a的AO上找到了 demo();// 执行到这的时候,a的AO早已被销毁,函数执行完,函数的执行期上下文会被销毁,但不是消失,而是a与AO的连线不见了 ,但是b因为被保存到外部了,所以b没有断,b指向的是a的劳动成果,把a的AO带到外部了,这就形成了闭包 demo()//102 </script>