搜尋

首頁  >  問答  >  主體

JavaScript閉包的工作原理是什麼?

<p>如何向一個對JavaScript閉包的概念(例如函數、變數等)有了解,但不理解閉包本身的人解釋閉包? </p> <p>我看過維基百科上給出的Scheme範例,但不幸的是沒有幫助。 </p>
P粉494151941P粉494151941505 天前466

全部回覆(2)我來回復

  • P粉734486718

    P粉7344867182023-08-23 09:30:55

    在JavaScript中,每個函數都維護著與其外部詞法環境的連結。詞法環境是一個作用域內所有名稱(例如變數、參數)及其值的對應。

    所以,每當你看到 function 關鍵字時,該函數內部的程式碼可以存取在函數外部宣告的變數。

    function foo(x) {
      var tmp = 3;
    
      function bar(y) {
        console.log(x + y + (++tmp)); // 将输出 16
      }
    
      bar(10);
    }
    
    foo(2);

    這將輸出16,因為函數bar 閉包了參數x 和變數tmp,它們都存在於外部函數foo 的詞法環境中。

    函數 bar 與其與函數 foo 的詞法環境的連結一起,構成了一個閉包。

    函數不需要 回傳 來建立一個閉包。僅透過聲明,每個函數都會閉包其封閉的詞法環境,形成一個閉包。

    function foo(x) {
      var tmp = 3;
    
      return function (y) {
        console.log(x + y + (++tmp)); // 也将输出 16
      }
    }
    
    var bar = foo(2);
    bar(10); // 16
    bar(10); // 17

    上述函數也會輸出 16,因為 bar 中的程式碼仍然可以引用參數 x 和變數 tmp,儘管它們不再直接在作用域內。

    然而,由於 tmp 仍然存在於 bar 的閉包中,它可以被遞增。每次呼叫 bar 時,它都會遞增。

    閉包最簡單的範例是:

    var a = 10;
    
    function test() {
      console.log(a); // 将输出 10
      console.log(b); // 将输出 6
    }
    var b = 6;
    test();

    當JavaScript函數被呼叫時,會建立一個新的執行上下文 ec。除了函數參數和目標物件之外,該執行上下文還接收到呼叫執行上下文的詞法環境的鏈接,這意味著在外部詞法環境中聲明的變數(在上面的範例中,即ab)可以從ec 存取。

    每個函數都建立了一個閉包,因為每個函數都有與其外部詞法環境的連結。

    請注意,閉包中可見的是變數本身,而不是副本。

    回覆
    0
  • P粉904405941

    P粉9044059412023-08-23 00:50:56

    閉包是以下內容的配對:

    1. 一個函數和
    2. 對此函數外部作用域(詞法環境)的參考

    詞法環境是每個執行上下文(堆疊幀)的一部分,它是標識符(即局部變數名稱)和值之間的映射。

    JavaScript中的每個函數都保持對其外部詞法環境的參考。當函數被呼叫時,此引用用於配置建立的執行上下文。此引用使函數內部的程式碼能夠「看到」在函數外部聲明的變量,無論函數何時何地被呼叫。

    如果一個函數是由另一個函數呼叫的,那麼就會建立一系列對外部詞法環境的參考。這個鏈條稱為作用域鏈。

    在下面的程式碼中,inner與呼叫foo時所建立的執行上下文的詞法環境形成了閉包,閉包包含變數secret

    function foo() {
      const secret = Math.trunc(Math.random() * 100)
      return function inner() {
        console.log(`The secret number is ${secret}.`)
      }
    }
    const f = foo() // 无法直接从外部访问`secret`
    f() // 检索`secret`的唯一方法是调用`f`

    回覆
    0
  • 取消回覆