Sean's Blog

An image showing avatar

Hi, I'm Sean

這裡記錄我學習網站開發的筆記
歡迎交流 (ゝ∀・)b

LinkedInGitHub

Understand JavaScript #16 函式工廠 (Function Factory)

本文主要內容為探討「函式工廠」的相關知識。閉包有很多有用的地方,像是函式工廠就是用閉包建立的模式,文章內容也會包含重載函式、一級函式、執行環境等概念。

重載函式 (Function Overloading)

  • 重載函式:讓函式能夠有不同數量的參數

其實 JavaScript 沒有重載函式的概念,因為 JavaScript 中的函式就是物件,無法像其他程式語言一樣做到重載函式,不過 JavaScript 卻有一級函式的概念,因此也可以做到相似的函式處理。

假設今天有一個 greet 函式,但我不想每次都傳入 language 這個參數,我們可以設定預設值,使用時則傳入不同語言的參數,就能以不同語言來打招呼。

1function greet(firstname, lastname, language) {
2  language = language || 'en';
3  if (language === 'en') {
4    console.log(`Hello ${firstname} ${lastname}`);
5  }
6  if (language === 'es') {
7    console.log(`Hola ${firstname} ${lastname}`);
8  }
9}
10
11greet('Damao', 'Huang', 'en');
12greet('Damao', 'Huang', 'es');

我們可以再加強以上寫法,使用類似重載函式的寫法,讓函式不用傳入這麼多資訊。

例如:另外創造兩個函式,再將特定的參數值 enes 分別先帶入函式的內容中。完成後,如果要用英文打招呼就呼叫 greetEnglish 函式,用西班牙語則呼叫 greetSpanish 函式,這樣在使用時就不用考慮 language 這個參數了。

1function greetEnglish(firstname, lastname) {
2  greet(firstname, lastname, 'en');
3}
4
5function greetSpanish(firstname, lastname) {
6  greet(firstname, lastname, 'es');
7}
8
9greetEnglish('Damao', 'Huang');
10greetSpanish('Damao', 'Huang');

這種類似重載函式的寫法是一個在 JavaScript 中比較簡單的模式,可以幫助我們更清楚地瞭解每個函式的用途,接下來我們以此為基礎,進階到函式工廠這個設計模式。

函式工廠 (Function Factory)

  • 工廠函式:會回傳一個幫我做事的函式

工廠函式 makeGreeting 會回傳一個函式給我們,這個函式的邏輯與剛才的 greet 函式相同,只差在參數 language 被移到外部函式。

當內部函式被呼叫時,language 會被包在閉包裡面,它是一個「自由變數」,內部函式隨著範圍鏈往外找就可以參考到它。

1function makeGreeting(language) {
2  return function (firstname, lastname) {
3    if (language === 'en') {
4      console.log(`Hello ${firstname} ${lastname}`);
5    }
6    if (language === 'es') {
7      console.log(`Hola ${firstname} ${lastname}`);
8    }
9  };
10}
11
12var greetEnglish = makeGreeting('en');
13var greetSpanish = makeGreeting('es');
14
15greetEnglish('Damao', 'Huang');
16greetSpanish('Damao', 'Huang');

接著我們執行了兩次 makeGreeting,雖然這是同一個函式(詞彙環境相同),但是執行兩次就會產生兩個不同的執行環境,因此產生的兩個變數 language記憶體位址是不同的。

makeGreeting

這就是閉包的特性,它讓內部函式記得自己是在何時何地被創造的,內部函式可以正確地參考到自己的外部函式的執行環境,也能參考到應該要找的自由變數的記憶體空間位置,一切就好像其他函式的執行環境還沒消失一樣。

使用閉包與函式工廠的概念,我們不用每次都傳入相同的參數,而是直接創造新的函式,透過閉包去製造預設的參數。

回顧

看完這篇文章,我們到底有什麼收穫呢?藉由本文可以理解到…

  • 重載函式的概念以及在 JavaScript 中類似的撰寫模式
  • 瞭解函式工廠的概念,使用其他函式創造函式

References