閉包

Frontend SELF TW
等級 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
問卷/小測驗
日期, Timer 和字面量,等級 37,課堂 5
未開放
日期, Timer 和字面量
日期, Timer 和字面量
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION