作用域、作用域链

  • 运行期上下文(AO):函数执行时会创建一个称为执行期上下文的内部对象
    • 一个AO定义了一个函数执行时的环境
    • 函数每次执行时创建新的AO,多次调用函数会创建多个AO,
    • 函数每次执行时,将新生成的AO放到作用域链的最顶端,函数执行完时被销毁
  • 作用域:
    • [[scope]]:作用域存储了运行期上下文的集合
    • 作用域链:[[scope]]中存储的运行期上下文对象的集合,集合呈链式连接
      查找变量:从作用域链顶端依次向下查找
      (./demo/js/闭包.html)
  1. <script>
  2. function a() {
  3. console.log(a); // undefined
  4. console.log(b); // function b
  5. function b() {
  6. var b = 234;
  7. console.log(b); //234
  8. }
  9. console.log(b); //function b
  10. var a = 123;
  11. console.log(a); // 123
  12. return b;
  13. }
  14. var glob = 100;
  15. var demo = a();
  16. demo();
  17. </script>
  18. /*
  19. 作用域链:
  20. a被定义时“./img/作用域链1.png”, a defined a.[[scope]] --> 0:GO
  21. a被执行时,b被定义
  22. “./img/作用域链2.png”, a activated a.[[scope]] --> 0:aAO
  23. 1: GO
  24. b defined b.[[scope]] --> 0:aAO
  25. 1: GO
  26. b被执行“./img/作用域链3.png” b activated b.[[scope]] --> 0: bAO
  27. 1: aAO
  28. 2: GO
  29. */
  • 闭包
    • a被执行时,b被定义,同时b被demo保存
    • a被销毁时,b仍然存在,“./img/闭包.png”
    • 因此可以在外部通过函数demo访问a中的变量

闭包

函数A内申明并保存在外部(被外部变量指向),可通过函数B使用A内部的局部变量或形参。外界对A函数内变量的引用导致其作用域不能被释放,构成一个闭包。

  1. function Counter() {
  2. let num = 0;
  3. return {
  4. add() {
  5. num++;
  6. console.log(num);
  7. }
  8. }
  9. }
  10. let counter = Counter();
  11. Counter.add() // 1
  12. Counder.add() // 2

闭包的作用

  • 做缓存(存储结构)
  • 模块化开发,防止污染全局变量
  • 实现封装
  1. // 封装 类 数据结构
  2. function cache = !() => {
  3. const store = {};
  4. return {
  5. get(key) {
  6. return store[key];
  7. }
  8. set(key, val) {
  9. store[key] = val;
  10. }
  11. remove(key) {
  12. delete store[key];
  13. }
  14. }
  15. }
  16. console.log(cache);
  17. cache.set('name': 'nini');
  18. cache.get('name'); // 'nini'
  • 暂存数据

JS 函数的执行机制

  1. // 将多个函数存储到数组中
  2. function test(){
  3. var arr = [];
  4. for(var i = 0; i < 10; i++) {
  5. (function(j){
  6. arr[j] = function(){
  7. document.write(j+'');
  8. }(i));
  9. }
  10. return arr;
  11. }
  12. var myArr = test();
  13. for(var j = 0; j < 10; j++) {
  14. myArr[j]();
  15. }

闭包的缺点

闭包内存得不到释放,容易造成内存泄漏