一、作用域、作用域链
- 每一个函数的作用域链上都有GO(全局执行期上下文);
- 当函数被定义的时候,已经形成作用域([[scope]]),已经形成作用域链:scope chain,作用域链里面已经存在GO了,在函数执行前一刻生成自己的AO;
二、闭包基础
- 当内部函数被返回到外部并保存时,一定会产生闭包;
- 闭包会产生原来的作用域不释放;
- 过度的闭包可能会导致内存泄露,或者加载过慢;
闭包案例1:
/**
* GO = {
* c : undefined -> 3
* test3 : undefined -> function test2() {}
* test1 : function test1() {}
* }
*
* test1的AO
* AO = {
* a : undefined -> 1
* test2: function test2() {}
* }
*
* test2的AO
* AO = {
* b : undefined -> 2
* }
*/
function test1() {
function test2() {
var b = 2;
console.log(a); // 1
}
var a = 1;
return test2;
}
var c = 3;
var test3 = test1(); //test1()里面return了test2 所以这一步将test2保存到了window下
test3();
// test3()执行完后,test1()的AO是要销毁的,但是test2()被保存到全局下,
// test2()里面用到了test1()的a,所以test1()的a也被保存到了全局下,不销毁,
// 也就是闭包会产生原来的作用域不释放
//打印结果: 1
/**
* test1定义: test1.[[scope]] -> 0: GO
* test1执行: test1.[[scope]] -> 0: test1的AO
* 1:GO
* test2定义: test2.[[scope]] -> 0: test1的AO
* 1:GO
* test2执行: test2.[[scope]] -> 0: test2的AO
* 1: test1的AO
* 2:GO
* test1结束: test1.[[scope]] -> 0: GO
* test2结束: test2.[[scope]] -> 0: test1的AO
* 1: GO
* test1.[[scope]] 销毁
*
*/
闭包案例2:
function test(){
var n = 100;
function add(){
n++;
console.log(n);
}
function reduce(){
n--;
console.log(n);
}
return [add,reduce];
}
var arr = test(); //将[add,reduce]保存到全局的arr[]中,
arr[0](); //执行add(); 打印结果:101,将test()的AO->变量n保存到全局中
arr[1](); //执行reduce(); 打印结果:100 (101-1=100)
/**
* 1. 预编译:
*
* GO = {
* arr : undefined -> [add, reduce]
* test: function test() {...}
* }
*
* AO = {
* n : undefined -> 100
* add : function add() {...}
* reduce: function reduce() {...}
* }
*
*/
/**
* 2.函数执行过程:
*
* test定义: test.[[scope]] -> 0 : GO
* test执行: test.[[scope]] -> 0 : test的AO
* 1 : GO
* add定义: add.[[scope]] -> 0: test的AO
* 1: GO
* add执行: add.[[scope]] -> 0: add的AO
* 1: test的AO
* 2: GO
* reduce定义: reduce.[[scope]] -> 0: test的AO
* 1: GO
* reduce执行: reduce.[[scope]] -> 0: reduce的AO
* 1: test的AO
* 2: GO
*/
闭包案例+分析合集:
【1】
【2】
【3】
【4】
【5】
【6】
【7】
【8】
【9】
【10】
【11】
【12】
【13】