作用域

GO/AO产生的一系列关于问题。 如何利用AO/GO去说明一些问题。
AO->function ->独立的仓库

  • 对象
    • 属性
    • 方法
  • 函数也是一种对象类型,引用类型(Object,Array,Function),引用值。
    • 属性
      • name
      • length//形参个数
      • prototype
  • 对象的属性无法访问

    • js引擎内部固有的隐式属性 私有属性。

      [[scope]]

  • 函数被创建的时候产生了一个js内部的隐式属性(只能被js引擎读取)。

  • 函数存储作用域链的地方。 作用域链里存储的是AO/GO
    • AO 函数的执行期上下文
    • GO 全局的执行期上下文(包含了 window 函数声明,变量声明)
    • 函数执行完成之后,就会销毁自己的AO。再次执行会重新生一个新的AO
    • AO 是一个即时存储容器
    • 全局执行前一刻,生成了GO->全局函数被定义的时候生成了自己的作用域和作用域链。

[[scope]] scope chain(作用域链)
GO

  1. function a(){
  2. function b(){
  3. var b = 2;
  4. }
  5. var a = 2;
  6. b();
  7. }
  8. a();
  • 解释
  1. 全局在执行的时候,a被定义的时候生成了一个[[scope]]属性的时候,scope 里面存储作用域链。
  2. scope作用域 第0位存储的是GO;
  3. a执行的前一刻 生成了自己的AO 此时a函数作用域链第0位存储的是a函数的AO. 第二位是全局GO;
  4. b在被定义是-> b函数的作用域链

分析作用域链

  1. function a(){
  2. function b(){
  3. function c(){
  4. }
  5. c();
  6. }
  7. b();
  8. }
  9. a();
  10. /***
  11. * a 定义:a.[[scope]] -> 0:GO
  12. * a 执行:a.[[scope]] -> 0:a的AO
  13. * 1:GO
  14. *
  15. * b 定义 b.[[scope]] -> 0:a的AO
  16. * 1:GO
  17. *
  18. * b 执行 b.[[scope]] -> 0:b的AO
  19. * 1:a的AO
  20. * 2:GO
  21. *
  22. * c 定义 c.[[scope]] -> 0:b的AO
  23. * 1:a的AO
  24. * 2:GO
  25. *
  26. * c 执行 c.[[scope]] -> 0:c的AO
  27. * 1:b的AO
  28. * 2:a的AO
  29. * 3:GO
  30. *
  31. * c 结束 c.[[scope]] -> 0:b的AO
  32. * 1:a的AO
  33. * 2:GO
  34. * b 结束 b.[[scope]] -> 0:a的AO
  35. * 1:GO
  36. * a 结束 a.[[scope]] -> 0:GO
  37. */

闭包

  • 当内部函数被返回到外部保存的时候,一定会产生闭包
  • 闭包会产生,原来的作用域链不释放
  • 过度闭包可能会导致内存泄漏,加载过慢

例子

  1. function test1(){
  2. function test2(){
  3. var b = 2;
  4. console.log(a);
  5. }
  6. var a = 1;
  7. return test2;
  8. }
  9. var test3 = test1();
  10. test3();
  11. /***
  12. * 事件 作用域[[scope]] 作用域链scope chain
  13. * test1 被定义的 test.scope 0:GO
  14. * test1 执行前一刻 test.scope 0:test.AO
  15. * 1:GO
  16. * tes1 执行
  17. * test2被定义 test2.scope 0:test.AO
  18. * 1:GO
  19. * test1 执行完毕 test1.scope 0:GO
  20. *
  21. * test3执行前一刻 test2生成了自己的AO 0:test2.AO
  22. * 1:test1.AO
  23. * 2:GO;
  24. * test3 执行
  25. * test3 执行完毕 GO 0:test1.AO test1的AO一直未被释放
  26. * 1:GO
  27. */
  1. function test(){
  2. var n = 100;
  3. function add(){
  4. n++;
  5. console.log(n);
  6. }
  7. function minus(){
  8. n--;
  9. console.log(n);
  10. }
  11. return [add,minus];//或者下面那个。
  12. return {
  13. add,minus
  14. }
  15. }
  16. var arr = test();
  17. arr[0]();//101
  18. arr[1]();//100
  19. /****
  20. * 全局预编译的时候生成GO
  21. * 作用域链
  22. * test 被定义 0:GO
  23. * test 执行前一刻 0:test.AO
  24. * 1:GO
  25. * test 被执行 test.AO={n:100,add:function(){},minus:function}
  26. *
  27. * add 被定义 0:test.AO
  28. * 1:GO
  29. * minus 被定义 0:test.AO
  30. * 1:GO
  31. * add minus 被返回出去。形成闭包
  32. * test 执行完毕 0:GO
  33. *
  34. * add执行前 0:add.AO
  35. * 1:test.AO
  36. * 2:GO
  37. * add执行后 0:test.AO
  38. * 1:GO
  39. */