1. 程式人生 > 其它 >[ES6深度解析]4:Template strings(模板字串)

[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.nameaction插入到結果字串中。

到目前為止,這只是+操作符的一個稍微更好的語法,下面的細節是你所期望的:

  • 模板替換中的程式碼可以是任何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),您仍然必須小心處理不可信的資料,就像連線普通字串一樣。
  • 模板字串不處理數字和日期的特定語言格式,更不用說複數格式了。
  • 它們不是模板庫的替代品,就像MustacheNunjucks
  • 模板字串沒有任何用於迴圈的內建語法——例如,從陣列中構建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, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

    // Don't escape special characters in the template.
    s += templateData[i];
  }
  return s;
}

本文來自部落格園,作者:Max力出奇跡,轉載請註明原文連結:https://www.cnblogs.com/welody/p/15167427.html