# [Javascript] ES6 模板字串 (Template String) 知多少

# 小小的兩個 ` ` 學問可真不少

動態板模字串

動態板模字串

Javasciript 在 ES6 後迎來了一大變革,不僅增加了許許多多的語法特性,在「字串」的撰寫上也增加了更多實用、方便的撰寫方法。

今天要來介紹的就是一個看似簡單,但卻功能強大的語法特性 — 模板字串 (Template String) 。

# 模板字串

有別於以前使用單引號 ‘’ 或是雙引號 “”文字 / 符號 / 數字 包住,所謂的模板字串就是使用 ```` 框住的一串 文字 / 符號 / 數字

# 字串拚接

傳統的字串拼接寫法,我們習慣使用 + 將多個字串、變數串接起來,以下為例:

var str = 'example line: ' + line1 + '\n' + 'column: ' + column;

模板字串的寫法,我們可以使用 ${變數名稱} 直接將變數安插在整個字串的自訂位置。並且,模板字串支援換行符號,我們不再需要使用 \n 表示換行。

var str = `example line: ${line1}
column: ${column}`;

以上這兩種的差異顯而易見。模板字串解決了傳統字串拼接的一大痛點 — 使用 + 進行拼接導致字串內容被拆分得過於零散,閱讀與維護得成本都相對較高。

模板字串允許變數直接插入字串之中,盡量保持字串預期呈現的格式,使得讀者在見到字串時便可一目了然,減少了閱讀時人腦轉換字串結果的「成本」。

以上,是模板字串最常使用的用法。大約涵蓋了 80% 以上的使用情境。

大部分人一般時間應該也就是使用到這樣的功能足矣。

然而,你知道板模字串的功能遠遠比上述更加強大嗎?

接下來要介紹的,就是板模字串更加強大的使用方法 — 板模標籤

# Tagged Template Literals

不知道各位有沒有使用過諸如 Styled Component、Apollo Graphql… 這幾類工具?

在 Styled Component 中,提供如下的寫法

https://styled-components.com/

https://styled-components.com/

https://www.apollographql.com/docs/tutorial/schema/

https://www.apollographql.com/docs/tutorial/schema/

直接在模板字串之前使用函數,並且不需使用「括號 ( )」。

這是如何做到的?

這就是今天重點要說明的主題。

我們引用 MDN 上對於 Tagged Template Literals 的解釋。

標籤樣板字面值是一種更高級的樣板字面值形式,允許你透過 標籤函數 操作樣板字面值的輸出。

標籤函數的 第一個參數是一「字串陣列」其餘參數則是「處理過的表達式」 。最終,你可以返回一個經處理後的字串,甚至是完全不一樣的東西。

標籤函數的名稱可以是任何你想要的。

什麼意思?

意思是,我們只要定義一個 function 符合第一個參數為 string array, 第二個參數為 rest argument,即可作為標籤函數。

我們使用以下幾個實驗來使我們了解這段話的意思。

定義一個 function 我們取名為 print

  • 使用一個 純字串 看看

第一個參數將傳入的 string 變成了一個 array,而後面的 rest 沒有得到任何東西。

  • 使用 帶有變數的 Template String 看看

這次,我們看到第一個參數接收的 array 為依照 ${} 的位置間格而成的字串;而第二個參數則是將 ${} 內的變數收集起來。

如此我們就知道,這個 function 的運作原理如下圖所示,清楚明瞭了。

因此,我們其實可以利用這特性,來做更加多樣的字串處理。

例如,我們便可以利用此特性,設計一個依照接收參數動態調整的字串板模

var dynamicTamplateString = props => (str_ary, ...rest_ary) =>
    str_ary.reduce(
        (whole_str, cur_str, indx) => `${whole_str}${rest_ary[indx - 1](props)}${cur_str}`
    );

如此,我們便可以使用這個 helping function 寫一個自定義的模板。

const myTemplate = props => dynamicTamplateString(props)`I am a ${
    (props) => {
        if (props.sex === 'M' && props.age > 20) return 'man';
        else if (props.sex === 'M' && props.age <= 20) return 'boy';
        else if (props.sex === 'W' && props.age > 20) return 'woman';
        else if (props.sex === 'W' && props.age <= 20) return 'girl';
        return 'Geek';
    }
}, I'm ${
    props => props.age
} years old, and I'm ${
    props => props.tall > 180 ? 'very tall' : 'not quite tall'
}`;

如下表示。

# 結語

模板字串語法的使用情境很廣。了解這些特性,在未來程式開發中必定會大大提高效率。

# 參考資料

  • JavaScript ES6 Template Literals 字串樣版
  • MDN
  • The magic behind 💅 styled-components

Like z20240z's work