84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
如何向一個對JavaScript閉包的概念(例如函數、變數等)有了解,但不理解閉包本身的人解釋閉包?
我看過維基百科上給出的Scheme範例,但不幸的是沒有幫助。
在JavaScript中,每個函數都維護著與其外部詞法環境的連結。詞法環境是一個作用域內所有名稱(例如變數、參數)及其值的對應。
所以,每當你看到function關鍵字時,該函數內部的程式碼可以存取在函數外部宣告的變數。
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的詞法環境中。
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存取。
ec
a
b
每個函數都建立了一個閉包,因為每個函數都有與其外部詞法環境的連結。
請注意,閉包中可見的是變數本身,而不是副本。
閉包是以下內容的配對:
詞法環境是每個執行上下文(堆疊幀)的一部分,它是標識符(即局部變數名稱)和值之間的映射。
JavaScript中的每個函數都保持對其外部詞法環境的參考。當函數被呼叫時,此引用用於配置建立的執行上下文。此引用使函數內部的程式碼能夠「看到」在函數外部聲明的變量,無論函數何時何地被呼叫。
如果一個函數是由另一個函數呼叫的,那麼就會建立一系列對外部詞法環境的參考。這個鏈條稱為作用域鏈。
在下面的程式碼中,inner與呼叫foo時所建立的執行上下文的詞法環境形成了閉包,閉包包含變數secret:
inner
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`
在JavaScript中,每個函數都維護著與其外部詞法環境的連結。詞法環境是一個作用域內所有名稱(例如變數、參數)及其值的對應。
所以,每當你看到
function
關鍵字時,該函數內部的程式碼可以存取在函數外部宣告的變數。這將輸出
16
,因為函數bar
閉包了參數x
和變數tmp
,它們都存在於外部函數foo
的詞法環境中。函數
bar
與其與函數foo
的詞法環境的連結一起,構成了一個閉包。函數不需要回傳來建立一個閉包。僅透過聲明,每個函數都會閉包其封閉的詞法環境,形成一個閉包。
上述函數也會輸出 16,因為
bar
中的程式碼仍然可以引用參數x
和變數tmp
,儘管它們不再直接在作用域內。然而,由於
tmp
仍然存在於bar
的閉包中,它可以被遞增。每次呼叫bar
時,它都會遞增。閉包最簡單的範例是:
當JavaScript函數被呼叫時,會建立一個新的執行上下文
ec
。除了函數參數和目標物件之外,該執行上下文還接收到呼叫執行上下文的詞法環境的鏈接,這意味著在外部詞法環境中聲明的變數(在上面的範例中,即a
和b
)可以從ec
存取。每個函數都建立了一個閉包,因為每個函數都有與其外部詞法環境的連結。
請注意,閉包中可見的是變數本身,而不是副本。
閉包是以下內容的配對:
詞法環境是每個執行上下文(堆疊幀)的一部分,它是標識符(即局部變數名稱)和值之間的映射。
JavaScript中的每個函數都保持對其外部詞法環境的參考。當函數被呼叫時,此引用用於配置建立的執行上下文。此引用使函數內部的程式碼能夠「看到」在函數外部聲明的變量,無論函數何時何地被呼叫。
如果一個函數是由另一個函數呼叫的,那麼就會建立一系列對外部詞法環境的參考。這個鏈條稱為作用域鏈。
在下面的程式碼中,
inner
與呼叫foo
時所建立的執行上下文的詞法環境形成了閉包,閉包包含變數secret
: