在 ES2015(也稱為 ES6)中引入的樣板文字提供了一種新的聲明字符串的方式,同時還提供了一些新的有趣的構造方法,並且已經被廣泛地使用。

樣板文字介紹

樣板文字是 ES2015 / ES6 中的一個新功能,與 ES5 及其以下版本相比,它以一種新穎的方式處理字符串。

從外觀上看,語法非常簡單,只需使用反引號(`)而不是單引號或雙引號即可:

const a_string = `something`

它們之所以獨一無二,是因為它們提供了很多普通字符串所不具備的功能,尤其是:

  • 它們提供了一種很好的語法來定義多行字符串
  • 它們提供了一種簡單的方式將變量和表達式插入字符串中
  • 它們允許您使用樣板標籤創建特定領域的語言(DSL,即“domain specific language”),例如 React 中的 Styled Components 用於為組件定義 CSS

讓我們逐一詳細介紹這些功能。

多行字符串

在 ES6 之前,要創建跨兩行的字符串,您必須在行末使用反斜線字符(\):

const string =
 'first part \
second part'

這允許在兩行上創建字符串,但實際呈現在只有一行上:

first part second part

要將字符串呈現為多行,您需要在每行末尾明確添加 \n,如下所示:

const string =
 'first line\n \
second line'

或者

const string = 'first line\n' + 'second line'

樣板文字使多行字符串變得更簡單。

一旦使用反引號打開樣板文字,您只需按 Enter 鍵即可換行,不需要特殊字符,並且渲染的結果就是原樣:

const string = `Hey
this

string
is awesome!`

請記住,空格是有意義的,因此這樣做:

const string = `First
 Second`

會產生以下字符串:

First
 Second

解決這個問題的一種簡單方法是在第一行留空,然後在最後的反引號後面添加 trim() 方法,該方法將刪除第一個字符之前的任何空格:

const string = `
First
Second`.trim()

插值

樣板文字提供了一種簡單的方式將變量和表達式插入字符串中。

通過使用 ${...} 語法來實現插值:

const myVariable = 'test'
const string = `something ${myVariable}` //something test

${} 中,您可以添加任何內容,甚至是表達式:

const string = `something ${1 + 2 + 3}`
const string2 = `something ${doSomething() ? 'x' : 'y'}`

樣板標籤

模板標籤(Tagged templates)是一種可能一開始對您來說看起來不是很有用的功能,但它實際上被許多廣泛使用的庫(如 Styled Components 或 Apollo - 一個用於定義 GraphQL 查詢模式的客/服務器庫)所使用,因此理解其工作原理是非常重要的。

在 Styled Components 中,模板標籤用於定義 CSS 字符串:

const Button = styled.button`
 font-size: 1.5em;
 background-color: black;
 color: white;
`

在 Apollo 中,模板標籤用於定義 GraphQL 查詢模式:

const query = gql`
 query {
 ...
 }
`

上述示例中突出顯示的 styled.buttongql 模板標籤只是函數

function gql(literals, ...expressions) {}

這個函數返回一個字符串,它可以是任意計算的結果。

literals 是一個包含由表達式插值化樣板文字內容的數組。

expressions 包含所有插值。

如果我們觀察上面的例子:

const string = `something ${1 + 2 + 3}`

在這種情況下,literals 是一個包含兩個項目的數組。第一個項目是 something,從第一個插值(我們只有一個插值)之前的字符串開始,第二個項目是一個空字符串,即第一個插值結束(这里只有一个插值)和字符串結束之間的空格。

expressions 在這個例子中是一個包含一個元素 6 的數組。

更複雜的例子是:

const string = `something
another ${'x'}
new line ${1 + 2 + 3}
test`

在這種情況下,literals 是一個包含三個項目的數組。第一個項目是:

;`something
another `

第二個項目是:

;`
new line `

第三個項目是:

;`
test`

expressions 在這種情況下是一個包含兩個元素 x6 的數組。

傳遞這些值的函數可以對其進行任何操作,這就是這種特性的強大之處。

最簡單的例子是模擬字符串插值,只需將 literalsexpressions 結合起來:

const interpolated = interpolate`I paid ${10}€`

這就是 interpolate 函數的工作方式:

function interpolate(literals, ...expressions) {
 let string = ``
 for (const [i, val] of expressions.entries()) {
 string += literals[i] + val
 }
 string += literals[literals.length - 1]
 return string
}