作用域
GO/AO产生的一系列关于问题。 如何利用AO/GO去说明一些问题。
AO->function ->独立的仓库
- 对象
- 属性
- 方法
- 函数也是一种对象类型,引用类型(Object,Array,Function),引用值。
- 属性
- name
- length//形参个数
- prototype
- 属性
对象的属性无法访问
函数被创建的时候产生了一个js内部的隐式属性(只能被js引擎读取)。
- 函数存储作用域链的地方。 作用域链里存储的是AO/GO
- AO 函数的执行期上下文
- GO 全局的执行期上下文(包含了 window 函数声明,变量声明)
- 函数执行完成之后,就会销毁自己的AO。再次执行会重新生一个新的AO
- AO 是一个即时存储容器
- 全局执行前一刻,生成了GO->全局函数被定义的时候生成了自己的作用域和作用域链。
[[scope]] scope chain(作用域链)
GO
function a(){
function b(){
var b = 2;
}
var a = 2;
b();
}
a();
- 解释
- 全局在执行的时候,a被定义的时候生成了一个[[scope]]属性的时候,scope 里面存储作用域链。
- scope作用域 第0位存储的是GO;
- a执行的前一刻 生成了自己的AO 此时a函数作用域链第0位存储的是a函数的AO. 第二位是全局GO;
- b在被定义是-> b函数的作用域链
分析作用域链
function a(){
function b(){
function c(){
}
c();
}
b();
}
a();
/***
* a 定义:a.[[scope]] -> 0:GO
* a 执行:a.[[scope]] -> 0:a的AO
* 1:GO
*
* b 定义 b.[[scope]] -> 0:a的AO
* 1:GO
*
* b 执行 b.[[scope]] -> 0:b的AO
* 1:a的AO
* 2:GO
*
* c 定义 c.[[scope]] -> 0:b的AO
* 1:a的AO
* 2:GO
*
* c 执行 c.[[scope]] -> 0:c的AO
* 1:b的AO
* 2:a的AO
* 3:GO
*
* c 结束 c.[[scope]] -> 0:b的AO
* 1:a的AO
* 2:GO
* b 结束 b.[[scope]] -> 0:a的AO
* 1:GO
* a 结束 a.[[scope]] -> 0:GO
*/
闭包
- 当内部函数被返回到外部保存的时候,一定会产生闭包
- 闭包会产生,原来的作用域链不释放
- 过度闭包可能会导致内存泄漏,加载过慢
例子
function test1(){
function test2(){
var b = 2;
console.log(a);
}
var a = 1;
return test2;
}
var test3 = test1();
test3();
/***
* 事件 作用域[[scope]] 作用域链scope chain
* test1 被定义的 test.scope 0:GO
* test1 执行前一刻 test.scope 0:test.AO
* 1:GO
* tes1 执行
* test2被定义 test2.scope 0:test.AO
* 1:GO
* test1 执行完毕 test1.scope 0:GO
*
* test3执行前一刻 test2生成了自己的AO 0:test2.AO
* 1:test1.AO
* 2:GO;
* test3 执行
* test3 执行完毕 GO 0:test1.AO test1的AO一直未被释放
* 1:GO
*/
function test(){
var n = 100;
function add(){
n++;
console.log(n);
}
function minus(){
n--;
console.log(n);
}
return [add,minus];//或者下面那个。
return {
add,minus
}
}
var arr = test();
arr[0]();//101
arr[1]();//100
/****
* 全局预编译的时候生成GO
* 作用域链
* test 被定义 0:GO
* test 执行前一刻 0:test.AO
* 1:GO
* test 被执行 test.AO={n:100,add:function(){},minus:function}
*
* add 被定义 0:test.AO
* 1:GO
* minus 被定义 0:test.AO
* 1:GO
* add minus 被返回出去。形成闭包
* test 执行完毕 0:GO
*
* add执行前 0:add.AO
* 1:test.AO
* 2:GO
* add执行后 0:test.AO
* 1:GO
*/