6 - 作用域、作用域链、闭包基础

77 阅读2分钟

一、作用域、作用域链

  1. 每一个函数的作用域链上都有GO(全局执行期上下文);
  2. 当函数被定义的时候,已经形成作用域([[scope]]),已经形成作用域链:scope chain,作用域链里面已经存在GO了,在函数执行前一刻生成自己的AO;

二、闭包基础

  1. 当内部函数被返回到外部并保存时,一定会产生闭包;
  2. 闭包会产生原来的作用域不释放;
  3. 过度的闭包可能会导致内存泄露,或者加载过慢;

闭包案例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