iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0
自我挑戰組

登堂入室!前端工程師的觀念技術 _30_ 題系列 第 3

2. 解釋 Closure ( Scope chain )

定義


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)。

可以參考前幾篇文章的這張圖回憶一下:
https://ithelp.ithome.com.tw/upload/images/20210903/20129476Q9VkPYnUJM.png

然後直接看例子:

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()時:

  1. f1()裡本身就定義了一個person(Tina)。
  2. console.log person時,調用了被定義在f1()裡的person(Tina)。
  3. 呼叫f2()

重點是,f2() 要去哪裡找person?

這時候就會發揮closure的作用,也就是說:

  1. 要console.log person時,發現沒有person → 往外層找
  2. 找到 global variable 的 person(Mary),把它印出來。

只記結論的話,就是當一個function要調用一個variable,而這個variable沒被定義在function裡,
function會從被定義的區塊/階層開始找變數。

Scope Chain


因此Closure也可以稱作Scope Chain,( 我自己理解成Closure就像是被串在一起的Scope們。)

每個Closure都包含三個Scope:

  • Local Scope (Own scope) → 當前的scope
  • Outer Functions Scope → 和Local Scope有階層關係的外層scope
  • Global 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()而言:

  1. f2() 本身是 Local Scope
  2. f1()f2() 來說是 Outer Functions Scope
  3. f1()之外都是 Global Scope

而最後印出的person,都是f1()裡的"Tina",這就是基於closure的特性。

由此可見,一個scope chain的順序關係會是
Local Scope (Own scope) → Outer Functions Scope → Global Scope

Closure vs. Scope


因為我自己在學的時候稍微會弄混,那為了更精闢的使用/了解這些特性,我試著用同個例子分別解釋各兩個名詞。

舉例:

let person = "Tina";

function f(){
    let person = "Winnie";
    console.log( person );
}

f(); // output: Winnie

因為scope是基於被宣告的位置,所以如果要解釋scope,可以說:

  1. let person = "Tina"; 有 global scope
  2. f() 會建立一個function scope
  3. let person = "Winnie"; 則是有 function scope

而如果要解釋closure,可以說:
f()會印出Winnie,是因為f()會從local scope裡開始找person,這是基於function創建了closure。
而f()在local scope找到了叫做"Winnie"的person,所以呼叫f()的結果會是Winnie。

參考資料:

【如果內文有誤,還希望請不吝指教>< 謝謝閱覽至此的各位:D】

-----正文結束-----

雖然請大家不吝指教,結果我發現我還不能回文,我失職QQ


上一篇
1. 解釋 Scope ( Global scope / Function scope / Block scope )
下一篇
3. 解釋 Hoisting
系列文
登堂入室!前端工程師的觀念技術 _30_ 題31

尚未有邦友留言

立即登入留言