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
。除了函數參數和目標物件之外,該執行上下文還接收到呼叫執行上下文的詞法環境的鏈接,這意味著在外部詞法環境中聲明的變數(在上面的範例中,即a
和b
)可以從ec
存取。
每個函數都建立了一個閉包,因為每個函數都有與其外部詞法環境的連結。
請注意,閉包中可見的是變數本身,而不是副本。
P粉9044059412023-08-23 00:50:56
閉包是以下內容的配對:
詞法環境是每個執行上下文(堆疊幀)的一部分,它是標識符(即局部變數名稱)和值之間的映射。
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`