• 什么是闭包


    一:闭包的概念:

    闭包是JavaScript中一个函数和它所在的词法环境的组合。词法环境是指函数声明时所处的作用域,这个环境包含了函数定义时的所有局部变量。当一个函数在其定义范围外被调用时,它仍然可以访问其外部词法环境中的变量,这就创建了一个闭包。

    二:闭包的工作原理:

    要理解闭包的工作原理,首先需要明白JavaScript的词法作用域规则。在JavaScript中,每个函数都有自己的作用域,它们可以访问自己内部的变量以及外部函数的变量。这意味着内部函数可以“捕获”外部函数的变量,即使外部函数已经执行完毕。

    下面是一个简单的例子,演示了闭包的工作原理:

    function parent() {
      var parentWord= "我是外面的函数变量";
      
      function child() {
        console.log(parentWord); // child函数访问了parentWord,形成了闭包
      }
      
      return child;
    }
    
    var result = parent();
    result(); // 输出 "我是外面的函数变量"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在上面的代码中,child 函数被返回并赋值给 result,然后在外部调用result 时,它仍然可以访问parentWord,尽管 parent 函数已经执行完毕。这就是闭包的本质:函数可以记住并访问其词法环境中的变量,即使这个环境不再处于活动状态。

    三:闭包的应用:

    1.封装数据:闭包可以用于创建私有变量,防止外部直接访问和修改数据。这是JavaScript模块模式的基础。

    function createCounter() {
      var count = 0;
      
      return {
        increment: function() {
          count++;
        },
        get: function() {
          return count;
        }
      };
    }
    
    var counter1 = createCounter();
    counter1.increment();
    console.log(counter1.get()); // 输出 1
    var counter2 = createCounter();
    counter2.increment();
    console.log(counter2.get()); // 输出 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    每次执行createCounter函数,得到的count都是独立的,互不影响。

    2.回调函数:闭包经常用于处理回调函数,保存一些状态或数据,以便在异步操作完成后使用。

    function fetchData(url, callback) {
      var data = null;
      // 模拟异步请求
      setTimeout(function() {
        data = "获取到data了:" + url;
        callback(data);
      }, 1000);
    }
    
    fetchData("example.com", function(result) {
      console.log(result); // 输出 "获取到data了:example.com"
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.循环中的问题:在循环中使用闭包可以解决常见的问题,例如在事件处理程序中正确捕获循环变量。

    for (var i = 0; i < 5; i++) {
      (function(index) {
        setTimeout(function() {
          console.log(index); // 输出 0, 1, 2, 3, 4
        }, 1000);
      })(i);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在ES6的块级作用域出来前,当我们在循环里面有异步操作时,就可以通过闭包的方式将这个i保存下来(如果直接访问 i,由于 i 是全局变量,最后打印出来的都是5)

  • 相关阅读:
    数据驱动!精细化运营!用机器学习做客户生命周期与价值预估!⛵
    分子相互作用的人工智能
    基于Windows API DialogBox的对话框
    Sentry的安装、配置、使用
    高并发场景下,6种方案,保证缓存和数据库的最终一致性!
    el-table支持分页多选
    离散数学 --- 图论基础 --- 无向图的连通性和有向图的连通性
    如何开家有品味的咖啡馆
    QT sqlite BLOB类型 写入数组
    自定义vue项目的雷达图组件
  • 原文地址:https://blog.csdn.net/brilliantSt/article/details/132867204