MDN的定義:
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).
In other words, a closure gives you access to an outer function’s scope from an inner function.
( 引用自 Closures - JavaScript | MDN )
『閉包(Closure)包含 函式以及該函式 被宣告時所在的作用域環境(lexical environment)。』
→ 環境包含閉包建立時,所有位於該作用域的區域變數。
而在JS的function creation phase裡,每次function建立時都會產生closure(Scope Chain)。
可以參考前幾篇文章的這張圖回憶一下:
然後直接看例子:
let person = "Mary";
function f1(){
let person = "Tina";
console.log( person + " is tall."); // person = Tina
f2();
}
function f2(){
console.log( person + " is cute."); // person = Mary
}
f1(); // output: Tina is tall. ; Mary is cute.
最後一行要呼叫f1()
時:
f1()
裡本身就定義了一個person
(Tina)。person
時,調用了被定義在f1()裡的person
(Tina)。f2()
f2()
要去哪裡找person
?這時候就會發揮closure的作用,也就是說:
person
時,發現沒有person → 往外層找person
(Mary),把它印出來。只記結論的話,就是當一個function要調用一個variable,而這個variable沒被定義在function裡,
function會從被定義的區塊/階層開始找變數。
因此Closure也可以稱作Scope Chain,( 我自己理解成Closure就像是被串在一起的Scope們。)
每個Closure都包含三個Scope:
改一下上面的例子:
// Global Scope
let person = "Mary";
function f1(){ // Outer Functions Scope
let person = "Tina";
console.log( person + " is tall.");
function f2(){
console.log( person + " is cute."); // Local Scope
}
f2();
}
f1(); // output: Tina is tall. ; Tina is cute.
所以這段script的階層關係是,以f2()
而言:
f2()
本身是 Local Scopef1()
對 f2()
來說是 Outer Functions Scopef1()
之外都是 Global Scope而最後印出的person
,都是f1()
裡的"Tina",這就是基於closure的特性。
由此可見,一個scope chain的順序關係會是
Local Scope (Own scope) → Outer Functions Scope → Global Scope
因為我自己在學的時候稍微會弄混,那為了更精闢的使用/了解這些特性,我試著用同個例子分別解釋各兩個名詞。
舉例:
let person = "Tina";
function f(){
let person = "Winnie";
console.log( person );
}
f(); // output: Winnie
因為scope是基於被宣告的位置,所以如果要解釋scope,可以說:
let person = "Tina";
有 global scopef()
會建立一個function scopelet person = "Winnie";
則是有 function scope而如果要解釋closure,可以說:
f()會印出Winnie,是因為f()會從local scope裡開始找person,這是基於function創建了closure。
而f()在local scope找到了叫做"Winnie"的person,所以呼叫f()的結果會是Winnie。
參考資料:
【如果內文有誤,還希望請不吝指教>< 謝謝閱覽至此的各位:D】
-----正文結束-----
雖然請大家不吝指教,結果我發現我還不能回文,我失職QQ