亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解JavaScript ES6中的模板字符串

 更新時(shí)間:2015年07月28日 10:21:11   作者:Jason Orendorff  
這篇文章主要介紹了詳解JavaScript ES6中的模板字符串,JS的ES6版本帶來(lái)諸多簡(jiǎn)潔化方面的重大改進(jìn),需要的朋友可以參考下

在 ES6 中引入了一種新的字符串字面量 — 模板字符串,除了使用反引號(hào) (`) 表示,它們看上去和普通的字符串沒(méi)有什么區(qū)別。在最簡(jiǎn)單的情況下,他們就是普通的字符串:

context.fillText(`Ceci n'est pas une cha?ne.`, x, y);
 
context.fillText(`Ceci n'est pas une cha?ne.`, x, y);

之所以被稱為模板字符串,是因?yàn)槟0遄址疄?JS 引入了簡(jiǎn)單的字符串插值特性,也就是說(shuō),可以方便優(yōu)雅地將 JS 的值插入到字符串中。

很多地方可以用到模板字符串,看下面這個(gè)不起眼的錯(cuò)誤提示消息:

function authorize(user, action) {
 if (!user.hasPrivilege(action)) {
  throw new Error(
   `User ${user.name} is not authorized to do ${action}.`);
 }
}
 
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 的值分別插到對(duì)應(yīng)的位置上,然后生成像這樣 “User jorendorff is not authorized to do hockey.” 的字符串。

現(xiàn)在,我們看到了一個(gè)比 + 運(yùn)算符更優(yōu)雅的語(yǔ)法,下面是一些你期待的特性:

    模板占位符可以是任何 JavaScript 表達(dá)式,所以函數(shù)調(diào)用和四則運(yùn)算等都是合法的。(甚至你還可以在一個(gè)模板字符串中嵌套另一個(gè)模板字符串。)
    如果一個(gè)值不是字符串,它將被轉(zhuǎn)換為字符串。例如,如果 action 是一個(gè)對(duì)象,那么該對(duì)象的 .toString() 將被調(diào)用,來(lái)將其轉(zhuǎn)換為字符串。
    如果你想在模板字符串中使用反引號(hào),你需要使用反斜杠 \ 將其轉(zhuǎn)義。
    同樣地,如果想在模板字符串中輸出 ${,也需要使用反斜杠將其轉(zhuǎn)義:\${ 或 $\{。
    模板字符串可以跨越多行:

$("#warning").html(`
 <h1>Watch out!</h1>
 <p>Unauthorized hockeying can result in penalties
 of up to ${maxPenalty} minutes.</p>
`);
 
$("#warning").html(`
 <h1>Watch out!</h1>
 <p>Unauthorized hockeying can result in penalties
 of up to ${maxPenalty} minutes.</p>
`);

    模板字符串中所有的空格、換行和縮進(jìn),都將被原樣輸出到結(jié)果字符串中。

下面我們來(lái)看看模板字符串做不到的事情:

    不會(huì)自動(dòng)轉(zhuǎn)義特殊字符,為了避免跨站腳本漏洞,你還是需要小心對(duì)待不可信的數(shù)據(jù),這一點(diǎn)上與普通字符串一樣。
    不能與國(guó)際化庫(kù)配合使用,不處理特殊語(yǔ)言格式的數(shù)字、日期等。
    不是模板引擎(比如 MustacheNunjucks)的替代品。模板字符串沒(méi)有處理循環(huán)的語(yǔ)法 — 不能通過(guò)一個(gè)數(shù)組構(gòu)建出一個(gè)表格(table)。

為了解決這些限制,ES6 為開(kāi)發(fā)者和庫(kù)設(shè)計(jì)者提供了另一種模板字符串 — 標(biāo)簽?zāi)0濉?/p>

標(biāo)簽?zāi)0宓恼Z(yǔ)法很簡(jiǎn)單,只需要在開(kāi)始的反引號(hào)前引入一個(gè)標(biāo)簽??吹谝粋€(gè)例子:SaferHTML,我們要使用這個(gè)標(biāo)簽?zāi)0鍋?lái)解決上述的第一個(gè)限制:自動(dòng)轉(zhuǎn)義特殊字符。

需要注意的是,SaferHTML 方法并不是 ES6 標(biāo)準(zhǔn)庫(kù)提供的,我們需要自己來(lái)實(shí)現(xiàn):

var message =
 SaferHTML`<p>${bonk.sender} has sent you a bonk.</p>`;
 
var message =
 SaferHTML`<p>${bonk.sender} has sent you a bonk.</p>`;

這里的 SaferHTML 標(biāo)簽是單個(gè)標(biāo)識(shí)符,標(biāo)簽也可以是屬性,比如 SaferHTML.escape,甚至還可以是方法調(diào)用:SaferHTML.escape({unicodeControlCharacters: false})。準(zhǔn)確地說(shuō),任何 ES6 的成員表達(dá)式或調(diào)用表達(dá)式都可以作為標(biāo)簽。

可以看出,模板字符串僅僅是字符串連接的語(yǔ)法糖,而標(biāo)簽?zāi)0宕_是一個(gè)完全不同的東西:函數(shù)調(diào)用。

所以,上面代碼等價(jià)于:

var message =
 SaferHTML(templateData, bonk.sender);
 
var message =
 SaferHTML(templateData, bonk.sender);

其中 templateData 是一個(gè)不可變的字符串?dāng)?shù)組,由 JS 引擎基于源模板字符串生成,這里的數(shù)組含有兩個(gè)元素,因?yàn)槟0遄址徽嘉环指艉蠛袃蓚€(gè)字符串,因此,templateData 將是這樣: Object.freeze(["<p>", " has sent you a bonk.</p>"]

(事實(shí)上,templateData 上還有另一個(gè)屬性:templateData.raw,本文并深入不討論該屬性。該屬性的值也是一個(gè)數(shù)組,包含了標(biāo)簽?zāi)0逯兴械淖址糠?,但字符串中包含了轉(zhuǎn)義序列,看上去更像源代碼中的字符串,比如 \n。ES6 的內(nèi)置標(biāo)簽 String.raw 將使用這些字符串。)

這就使得 SaferHTML 方法可以隨意解析這兩個(gè)字符串,存在 N 中替換方式。

在繼續(xù)閱讀錢(qián),你可能在苦苦思索如何實(shí)現(xiàn) SaferHTML 方法。

下面是一種實(shí)現(xiàn)(gist):

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;
}
 
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;
}

有了上面的方法,即使使用一個(gè)惡意的用戶名,用戶也是安全的。

一個(gè)簡(jiǎn)單的例子并不足以說(shuō)明標(biāo)簽?zāi)0宓撵`活性,讓我們重溫一下上面列舉的模板字符串的限制,看看我們還可以做些什么。

    模板字符串不會(huì)自動(dòng)轉(zhuǎn)義特殊字符,但是我們可以通過(guò)標(biāo)簽?zāi)0鍋?lái)解決這個(gè)問(wèn)題,事實(shí)上我們還可以將 SaferHTML 這個(gè)方法寫(xiě)的更好。從安全角度來(lái)看,這個(gè) SaferHTML 非常脆弱。在 HTML 中,不同的地方需要用不同的方式去轉(zhuǎn)義,SaferHTML 并沒(méi)有做到。稍加思考,我們就可以實(shí)現(xiàn)一個(gè)更加靈活的 SaferHTML方法,能夠?qū)?templateData 中的任何一個(gè) HTML 轉(zhuǎn)義,知道哪個(gè)占位符是純 HTML;哪個(gè)是元素的屬性,從而需要對(duì) ' 和 " 轉(zhuǎn)義;哪個(gè)是 URL 的 query 字符串,從而需要用 URL 的 escaping 方法,而不是 HTML 的 escaping;等等。這似乎有些牽強(qiáng),因?yàn)?HTML 轉(zhuǎn)義效率比較低。辛運(yùn)是的,標(biāo)簽?zāi)0宓淖址潜3植蛔兊?,SaferHTML 可以緩存已經(jīng)轉(zhuǎn)義過(guò)的字符串,從而提高效率。
    模板字符串并沒(méi)有內(nèi)置的國(guó)際化特性,但通過(guò)標(biāo)簽?zāi)0澹覀兛梢蕴砑釉撎匦浴?a target="_blank" >Jack Hsu 的文章詳細(xì)介紹了實(shí)現(xiàn)過(guò)程,看下面例子:

i18n`Hello ${name}, you have ${amount}:c(CAD) in your bank account.`
// => Hallo Bob, Sie haben 1.234,56 $CA auf Ihrem Bankkonto.




i18n`Hello ${name}, you have ${amount}:c(CAD) in your bank account.`
// => Hallo Bob, Sie haben 1.234,56 $CA auf Ihrem Bankkonto.

上面例子中的 name 和 amount 很好理解,將被 JS 引擎替換為對(duì)應(yīng)的字符串,但是還有一個(gè)沒(méi)有見(jiàn)過(guò)的占位符::c(CAD),這將被 i18n 標(biāo)簽處理,從 i18n 的文檔可知::c(CAD)表示 amount 是加拿大美元貨幣值。

    模板字符串不能替代 Mustache 和 Nunjucks 這類(lèi)模板引擎,部分原因在于模板字符串不支持循環(huán)和條件語(yǔ)句。我們可以編寫(xiě)一個(gè)標(biāo)簽來(lái)實(shí)現(xiàn)這類(lèi)功能:

// Purely hypothetical template language based on
// ES6 tagged templates.
var libraryHtml = hashTemplate`
 <ul>
  #for book in ${myBooks}
   <li><i>#{book.title}</i> by #{book.author}</li>
  #end
 </ul>
`;

 
// Purely hypothetical template language based on
// ES6 tagged templates.
var libraryHtml = hashTemplate`
 <ul>
  #for book in ${myBooks}
   <li><i>#{book.title}</i> by #{book.author}</li>
  #end
 </ul>
`;

靈活性還不止于此,需要注意的是,標(biāo)簽函數(shù)的參數(shù)不會(huì)自動(dòng)轉(zhuǎn)換為字符串,參數(shù)可以是任何類(lèi)型,返回值也一樣。標(biāo)簽?zāi)0迳踔量梢圆恍枰址?,你可以使用自定義標(biāo)簽來(lái)創(chuàng)建正則表達(dá)式、DOM 樹(shù)、圖片、代表整個(gè)異步進(jìn)程的 Promise、JS 數(shù)據(jù)結(jié)構(gòu)、GL 著色器…

標(biāo)簽?zāi)0逶试S庫(kù)設(shè)計(jì)者創(chuàng)建強(qiáng)大的領(lǐng)域特定語(yǔ)言。這些語(yǔ)言可能看上去并不像 JS,但他們可以無(wú)縫嵌入到 JS 中,并且可以與語(yǔ)言的其余部分進(jìn)行交互。順便說(shuō)一下,我還沒(méi)有在其他語(yǔ)言中見(jiàn)過(guò)類(lèi)似的特性,我不知道這個(gè)特性講給我們帶來(lái)些什么,但各種可能性還是非常令人興奮的。

相關(guān)文章

  • javascript克隆對(duì)象深度介紹

    javascript克隆對(duì)象深度介紹

    本文將詳細(xì)介紹js 深度克隆的分類(lèi)與實(shí)現(xiàn),需要的朋友可以參考下
    2012-11-11
  • javascript數(shù)組里的27個(gè)方法總合詳解

    javascript數(shù)組里的27個(gè)方法總合詳解

    這篇文章主要為大家詳細(xì)介紹了javascript數(shù)組里的方法27個(gè)總合,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • javascript創(chuàng)建數(shù)組之聯(lián)合數(shù)組的使用方法示例

    javascript創(chuàng)建數(shù)組之聯(lián)合數(shù)組的使用方法示例

    聯(lián)合數(shù)組也叫做鍵值數(shù)組,和php中的鍵值數(shù)組類(lèi)似,下面看代碼如何演示
    2013-12-12
  • javascript中的括號(hào)()用法小結(jié)

    javascript中的括號(hào)()用法小結(jié)

    ()作為一個(gè)數(shù)學(xué)運(yùn)算中的基本符號(hào),在計(jì)算機(jī)程序中也被大量使用,最基本的就是提高運(yùn)算優(yōu)先級(jí),JS中也不例外
    2014-04-04
  • js靜態(tài)作用域的功能。

    js靜態(tài)作用域的功能。

    js靜態(tài)作用域的功能。...
    2006-12-12
  • 最新評(píng)論