闭包

Frontend SELF ZH
第 37 级 , 课程 5
可用

6.1 闭包的概念

闭包是JavaScript中最强大和重要的概念之一。它们允许函数在执行之后仍然记住它们的词法环境。在这节课中,我们将探讨闭包的概念、特点,并展示其使用的各种示例。

JavaScript中的闭包(closure)是函数与其被声明时的词法环境的组合。闭包允许函数“记住”并访问其外部可见范围内的变量和其他函数,即使在外部函数执行完毕后。

闭包的主要特点:

  1. 词法环境:函数被声明时的上下文,包括声明时可用的所有变量。
  2. 保持上下文:拥有闭包的函数可以在外部函数执行完毕后仍然访问外部可见范围内的变量。

6.2 闭包的工作示例

示例 1:简单的闭包

在这个示例中,innerFunction()在其外部可见范围内访问变量outerVariable,即使在outerFunction()执行完毕之后。

JavaScript
    
      function outerFunction() {
        let outerVariable = 'I am from the outer function';

        function innerFunction() {
          console.log(outerVariable);
        }
        return innerFunction;
      }

      const closure = outerFunction();
      closure(); // 输出: I am from the outer function
    
  

示例 2:使用闭包的计数器

在这个示例中,计数器函数保存变量count的值,并在每次调用时增加它。

JavaScript
    
      function createCounter() {
        let count = 0;

        return function() {
          count++;
          return count;
        };
      }

      const counter = createCounter();

      console.log(counter()); // 输出: 1
      console.log(counter()); // 输出: 2
      console.log(counter()); // 输出: 3
    
  

示例 3:循环中的闭包

闭包常用于在循环中保存变量的值。

在这个示例中,数组arr中的每个函数在创建时通过let的块级作用域“记住”变量i的值:

JavaScript
    
      function createArrayWithClosures() {
        let arr = [];

        for (let i = 0; i < 3; i++) {
          arr[i] = function() {
            console.log(i);
          };
        }
        return arr;
      }

      const closures = createArrayWithClosures();

      closures[0](); // 输出: 0
      closures[1](); // 输出: 1
      closures[2](); // 输出: 2
    
  

6.3 闭包的复杂使用场景

示例 1:函数的部分应用(partial application)

闭包允许创建部分应用的函数,保持某些参数固定。

在这个示例中,函数multiply()返回一个函数,将传递的参数b乘以固定参数a

JavaScript
    
      function multiply(a) {
        return function(b) {
          return a * b;
        };
      }

      const double = multiply(2);
      console.log(double(5)); // 输出: 10
      console.log(double(10)); // 输出: 20
    
  

示例 2:数据隐藏(data hiding)

闭包可用于创建私有变量和方法。

在这个示例中,变量_name_age是私有的,仅通过对象的方法访问:

JavaScript
    
      function createPerson(name, age) {
        let _name = name;
        let _age = age;

        return {
          getName: function() {
            return _name;
          },
          getAge: function() {
            return _age;
          },
          setName: function(newName) {
            _name = newName;
          },
          setAge: function(newAge) {
            _age = newAge;
          }
        };
      }

      const person = createPerson('John', 30);
      console.log(person.getName()); // 输出: John

      person.setName('Jane');

      console.log(person.getName()); // 输出: Jane
      console.log(person.getAge());  // 输出: 30
    
  

示例 3:记忆化(memoization)

记忆化是一种优化技术,通过保存函数的结果来避免为相同输入进行重复计算。

在这个示例中,函数memoize()使用闭包保存函数fn()计算结果的缓存:

JavaScript
    
      function memoize(fn) {
        const cache = {};

        return function(...args) {
          const key = JSON.stringify(args);
          if (cache[key]) {
            return cache[key];
          }
          const result = fn(...args);
          cache[key] = result;
          return result;
        };
      }

      function slowFunction(num) {
        console.log('Computing...');
        return num * 2;
      }

      const memoizedFunction = memoize(slowFunction);

      console.log(memoizedFunction(5)); // 输出: Computing... 10
      console.log(memoizedFunction(5)); // 输出: 10 (结果从缓存中取出)
    
  
1
调查/小测验
Date, Timer 和 литералы第 37 级,课程 5
不可用
Date, Timer 和 литералы
Date, Timer 和 литералы
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION