[ES6深度解析]4:Template strings(模板字串)
撇號基礎知識(`)
ES6引入了一種新的字串字面量語法,稱為模板字串。它們看起來像普通的字串,除了使用反勾字元ˋ
而不是通常的引號'
或"
。在最簡單的情況下,它們實際上只是字串:
context.fillText(`Ceci n'est pas une chaîne.`, x, y);
但這些字串被稱為“模板字串”,而不是“沒有任何特殊功能,只有反引號的乏味的普通字串”是有原因的。模板字串給JavaScript帶來了簡單的字串插值。也就是說,它們是將JavaScript值插入字串的一種漂亮、方便的方法。有無數種方法可以使用它,但最能溫暖我心的是那句不起眼的錯誤資訊:
function authorize(user, action) { if (!user.hasPrivilege(action)) { throw new Error( `User ${user.name} is not authorized to do ${action}.`); } }
在這個例子中,${user.name}
和${action}
被稱為模板替換。JavaScript將把值user.name
和action
插入到結果字串中。
到目前為止,這只是+
操作符的一個稍微更好的語法,下面的細節是你所期望的:
- 模板替換中的程式碼可以是任何JavaScript表示式,因此允許函式呼叫、算術等。如果你願意,甚至可以在另一個模板字串中巢狀一個模板字串,稱之為模板初始化(template inception)
- 如果一個值都不是字串,它將使用通常的規則轉換為字串。例如,如果
action
是一個物件,它的.tostring()
方法將被呼叫。 - 如果你需要在模板字串中寫一個反勾號,你必須用反斜槓來轉義它:
\ˋ
"ˋ"
相同。 - 同樣,如果你需要在模板字串中包含兩個字元
${
,你可以用反斜槓:\${
或$\{
轉義字元。
與普通字串不同,模板字串可以包含多行:
$("#warning").html(`
<h1>Watch out!</h1>
<p>Unauthorized hockeying can result in penalties
of up to ${maxPenalty} minutes.</p>
`);
模板字串中的所有空格,包括換行符和縮排符,都將一字不差地包含在輸出中。
撇號的未來
讓我們來談談模板字串不能做的一些事情:
- 它們不會自動為您轉義特殊字元。為了避免跨站點指令碼漏洞(cross-site scripting),您仍然必須小心處理不可信的資料,就像連線普通字串一樣。
- 模板字串不處理數字和日期的特定語言格式,更不用說複數格式了。
- 它們不是模板庫的替代品,就像
Mustache
或Nunjucks
- 模板字串沒有任何用於迴圈的內建語法——例如,從陣列中構建HTML表的行——甚至沒有條件語句。
標記模板(tagged templates)
ES6在模板字串上又做了一個改進,讓JS開發人員和庫設計人員能夠解決這些限制等等。該特性稱為標記模板(tagged templates)。
標記
模板的語法很簡單。它們只是模板字串,在開始的反引號之前有一個額外的標籤。對於我們的第一個例子,標籤將是SaferHTML
,我們將使用這個標籤來嘗試解決上面列出的第一個限制:自動轉義特殊字元。
注意,SaferHTML
不是由ES6標準庫提供的。我們將在下面自己實現它。
var message = SaferHTML`<p>${bonk.sender} has sent you a bonk.</p>`;
這裡的標記
是單一識別符號SaferHTML
,但標記
也可以是一個屬性,如SaferHTML.escape
,甚至是一個方法呼叫,如SaferHTML.escape({unicodeControlCharacters: false})
。(更準確地說,任何ES6的MemberExpression或CallExpression都可以作為標記
。)
我們看到,不帶標記
模板字串是簡單字串連線的簡寫形式。帶標記
的模板是其他東西的簡寫:函式呼叫。
上面的程式碼相當於:
var message = SaferHTML(templateData, bonk.sender);
其中templateData
是模板中所有字串部分的不可變陣列,由JS引擎建立。在這裡,陣列將有兩個元素,因為在標記模板中有兩個字串部分,由,
分隔。所以templateData
會像Object.freeze(["<p>"," has sent you a bonk.</p>"]
。
實際上在templateData
上還有一個屬性。我們不會在本文中使用它,但是為了完整起見,我將提到它:templateData.raw
是另一個數組,包含了帶標籤的模板中的所有字串部分,但這一次與它們在原始碼中看到的完全一樣——像\n
這樣的轉義序列保持完整,而不是被轉換成換行符等等。標準標記String.raw
使用這些原始字串。
這使得SaferHTML函式
可以自由地以百萬種可能的方式解釋字串和替換。
在繼續閱讀之前,您可能想要嘗試弄清楚SaferHTML應該做什麼,然後嘗試自己實現它。畢竟,它只是一個函式。這裡有一個可能的答案:
function SaferHTML(templateData) {
var s = templateData[0];
for (var i = 1; i < arguments.length; i++) {
var arg = String(arguments[i]);
// Escape special characters in the substitution.
s += arg.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
// Don't escape special characters in the template.
s += templateData[i];
}
return s;
}
本文來自部落格園,作者:Max力出奇跡,轉載請註明原文連結:https://www.cnblogs.com/welody/p/15167427.html