亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

詳解JavaScript ES6中的模板字符串

2024-05-06 16:23:55
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了詳解JavaScript ES6中的模板字符串,JS的ES6版本帶來諸多簡潔化方面的重大改進,需要的朋友可以參考下

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

 

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

之所以被稱為模板字符串,是因為模板字符串為 JS 引入了簡單的字符串插值特性,也就是說,可以方便優雅地將 JS 的值插入到字符串中。

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

 

 
  1. function authorize(user, action) { 
  2. if (!user.hasPrivilege(action)) { 
  3. throw new Error( 
  4. `User ${user.name} is not authorized to do ${action}.`); 
  5.  
  6. function authorize(user, action) { 
  7. if (!user.hasPrivilege(action)) { 
  8. throw new Error( 
  9. `User ${user.name} is not authorized to do ${action}.`); 

上面代碼中,${user.name} 和 ${action} 被稱為模板占位符,JavaScript 將把 user.name和 action 的值分別插到對應的位置上,然后生成像這樣 “User jorendorff is not authorized to do hockey.” 的字符串。

現在,我們看到了一個比 + 運算符更優雅的語法,下面是一些你期待的特性:

模板占位符可以是任何 JavaScript 表達式,所以函數調用和四則運算等都是合法的。(甚至你還可以在一個模板字符串中嵌套另一個模板字符串。)

如果一個值不是字符串,它將被轉換為字符串。例如,如果 action 是一個對象,那么該對象的 .toString() 將被調用,來將其轉換為字符串。

如果你想在模板字符串中使用反引號,你需要使用反斜杠 / 將其轉義。

同樣地,如果想在模板字符串中輸出 ${,也需要使用反斜杠將其轉義:/${ 或 $/{。

模板字符串可以跨越多行:

 

 
  1. $("#warning").html(` 
  2. <h1>Watch out!</h1> 
  3. <p>Unauthorized hockeying can result in penalties 
  4. of up to ${maxPenalty} minutes.</p> 
  5. `); 
  6.  
  7. $("#warning").html(` 
  8. <h1>Watch out!</h1> 
  9. <p>Unauthorized hockeying can result in penalties 
  10. of up to ${maxPenalty} minutes.</p> 
  11. `); 

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

下面我們來看看模板字符串做不到的事情:

不會自動轉義特殊字符,為了避免跨站腳本漏洞,你還是需要小心對待不可信的數據,這一點上與普通字符串一樣。

不能與國際化庫配合使用,不處理特殊語言格式的數字、日期等。

不是模板引擎(比如Mustache或Nunjucks)的替代品。模板字符串沒有處理循環的語法 — 不能通過一個數組構建出一個表格(table)。

為了解決這些限制,ES6 為開發者和庫設計者提供了另一種模板字符串 — 標簽模板。

標簽模板的語法很簡單,只需要在開始的反引號前引入一個標簽。看第一個例子:SaferHTML,我們要使用這個標簽模板來解決上述的第一個限制:自動轉義特殊字符。

需要注意的是,SaferHTML 方法并不是 ES6 標準庫提供的,我們需要自己來實現:

 

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

這里的 SaferHTML 標簽是單個標識符,標簽也可以是屬性,比如 SaferHTML.escape,甚至還可以是方法調用:SaferHTML.escape({unicodeControlCharacters: false})。準確地說,任何 ES6 的成員表達式或調用表達式都可以作為標簽。

可以看出,模板字符串僅僅是字符串連接的語法糖,而標簽模板確是一個完全不同的東西:函數調用。

所以,上面代碼等價于:

 

 
  1. var message = 
  2. SaferHTML(templateData, bonk.sender); 
  3.  
  4. var message = 
  5. SaferHTML(templateData, bonk.sender); 

其中 templateData 是一個不可變的字符串數組,由 JS 引擎基于源模板字符串生成,這里的數組含有兩個元素,因為模板字符串被占位符分隔后含有兩個字符串,因此,templateData 將是這樣: Object.freeze(["

", " has sent you a bonk.

"]

 

(事實上,templateData 上還有另一個屬性:templateData.raw,本文并深入不討論該屬性。該屬性的值也是一個數組,包含了標簽模板中所有的字符串部分,但字符串中包含了轉義序列,看上去更像源代碼中的字符串,比如 /n。ES6 的內置標簽 String.raw 將使用這些字符串。)

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

在繼續閱讀錢,你可能在苦苦思索如何實現 SaferHTML 方法。

下面是一種實現(gist):

 

 
  1. function SaferHTML(templateData) { 
  2. var s = templateData[0]; 
  3. for (var i = 1; i < arguments.length; i++) { 
  4. var arg = String(arguments[i]); 
  5.  
  6. // Escape special characters in the substitution. 
  7. s += arg.replace(/&/g, "&"
  8. .replace(/</g, "<"
  9. .replace(/>/g, ">"); 
  10.  
  11. // Don't escape special characters in the template. 
  12. s += templateData[i]; 
  13. return s; 
  14.  
  15. function SaferHTML(templateData) { 
  16. var s = templateData[0]; 
  17. for (var i = 1; i < arguments.length; i++) { 
  18. var arg = String(arguments[i]); 
  19.  
  20. // Escape special characters in the substitution. 
  21. s += arg.replace(/&/g, "&"
  22. .replace(/</g, "<"
  23. .replace(/>/g, ">"); 
  24.  
  25. // Don't escape special characters in the template. 
  26. s += templateData[i]; 
  27. return s; 

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

一個簡單的例子并不足以說明標簽模板的靈活性,讓我們重溫一下上面列舉的模板字符串的限制,看看我們還可以做些什么。

模板字符串不會自動轉義特殊字符,但是我們可以通過標簽模板來解決這個問題,事實上我們還可以將 SaferHTML 這個方法寫的更好。從安全角度來看,這個 SaferHTML 非常脆弱。在 HTML 中,不同的地方需要用不同的方式去轉義,SaferHTML 并沒有做到。稍加思考,我們就可以實現一個更加靈活的 SaferHTML方法,能夠將 templateData 中的任何一個 HTML 轉義,知道哪個占位符是純 HTML;哪個是元素的屬性,從而需要對 ' 和 " 轉義;哪個是 URL 的 query 字符串,從而需要用 URL 的 escaping 方法,而不是 HTML 的 escaping;等等。這似乎有些牽強,因為 HTML 轉義效率比較低。辛運是的,標簽模板的字符串是保持不變的,SaferHTML 可以緩存已經轉義過的字符串,從而提高效率。

模板字符串并沒有內置的國際化特性,但通過標簽模板,我們可以添加該特性。Jack Hsu 的文章詳細介紹了實現過程,看下面例子:

 

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

上面例子中的 name 和 amount 很好理解,將被 JS 引擎替換為對應的字符串,但是還有一個沒有見過的占位符::c(CAD),這將被 i18n 標簽處理,從 i18n 的文檔可知::c(CAD)表示 amount 是加拿大美元貨幣值。

模板字符串不能替代 Mustache 和 Nunjucks 這類模板引擎,部分原因在于模板字符串不支持循環和條件語句。我們可以編寫一個標簽來實現這類功能:

 

 
  1. // Purely hypothetical template language based on 
  2. // ES6 tagged templates. 
  3. var libraryHtml = hashTemplate` 
  4. <ul> 
  5. #for book in ${myBooks} 
  6. <li><i>#{book.title}</i> by #{book.author}</li> 
  7. #end 
  8. </ul> 
  9. `; 
  10.  
  11.  
  12. // Purely hypothetical template language based on 
  13. // ES6 tagged templates. 
  14. var libraryHtml = hashTemplate` 
  15. <ul> 
  16. #for book in ${myBooks} 
  17. <li><i>#{book.title}</i> by #{book.author}</li> 
  18. #end 
  19. </ul> 
  20. `; 

靈活性還不止于此,需要注意的是,標簽函數的參數不會自動轉換為字符串,參數可以是任何類型,返回值也一樣。標簽模板甚至可以不需要字符串,你可以使用自定義標簽來創建正則表達式、DOM 樹、圖片、代表整個異步進程的 Promise、JS 數據結構、GL 著色器…

標簽模板允許庫設計者創建強大的領域特定語言。這些語言可能看上去并不像 JS,但他們可以無縫嵌入到 JS 中,并且可以與語言的其余部分進行交互。順便說一下,我還沒有在其他語言中見過類似的特性,我不知道這個特性講給我們帶來些什么,但各種可能性還是非常令人興奮的。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久女教师免费一区| 精品久久久久久久久久久久久| 黄色成人av在线| 国产亚洲精品久久久久久牛牛| 日韩在线免费视频| 欧美视频在线观看免费网址| 国产精品99一区| 8x拔播拔播x8国产精品| 欧美裸体男粗大视频在线观看| 亚洲精品综合精品自拍| 久久久久久中文字幕| www国产精品com| 国产一区二区三区18| 精品无人区乱码1区2区3区在线| 青青草原成人在线视频| 一本大道亚洲视频| 一区二区三区四区在线观看视频| 亚洲级视频在线观看免费1级| 欧美日韩另类字幕中文| 伊是香蕉大人久久| 欧美黄色成人网| 久久天天躁狠狠躁夜夜av| 欧美巨大黑人极品精男| 亚洲精品一区二三区不卡| 九九久久久久久久久激情| 日本一本a高清免费不卡| 日本久久精品视频| 国产亚洲激情在线| 日韩欧美中文字幕在线播放| 美日韩精品免费视频| 亚洲乱码国产乱码精品精天堂| 欧美乱大交xxxxx另类电影| 92国产精品久久久久首页| 亚洲欧美综合精品久久成人| 亚洲欧美日韩第一区| 国产精品久久久久秋霞鲁丝| 国产成人精品在线播放| 91国产精品电影| 亚洲电影av在线| 91国产精品电影| 国产精品手机播放| 国语自产精品视频在线看抢先版图片| 亚洲国产精品yw在线观看| 最近2019中文免费高清视频观看www99| 81精品国产乱码久久久久久| 欧美电影在线观看网站| 欧美日韩在线一区| 国产欧美日韩丝袜精品一区| 亚洲精品98久久久久久中文字幕| 亚洲香蕉在线观看| 国产精品人成电影| 国产精品尤物福利片在线观看| 亚洲高清一二三区| 国产日韩精品在线观看| 精品国偷自产在线| 亚洲国产日韩精品在线| 欧美激情亚洲一区| 国产成人精品a视频一区www| 国产精品女人网站| 日韩欧美一区二区在线| 久久久国产一区二区| 色爱av美腿丝袜综合粉嫩av| 91精品国产综合久久香蕉的用户体验| 成人国产精品色哟哟| 丁香五六月婷婷久久激情| 96pao国产成视频永久免费| 久久伊人精品一区二区三区| 中文国产亚洲喷潮| 麻豆国产va免费精品高清在线| 亚洲精品自拍第一页| 91在线播放国产| 日本成人精品在线| 成人黄色av播放免费| 亚洲精品国产精品乱码不99按摩| 国产精品久久久久久久av大片| 精品久久久av| zzijzzij亚洲日本成熟少妇| 亚洲欧美日韩网| 欧美电影免费观看高清完整| 国产精品成人免费视频| 91精品啪在线观看麻豆免费| 国自产精品手机在线观看视频| 久久久久北条麻妃免费看| 欧美性猛交99久久久久99按摩| 久久香蕉国产线看观看av| 日韩精品一二三四区| 国产中文日韩欧美| 一本大道久久加勒比香蕉| 欧美亚洲激情在线| 亲爱的老师9免费观看全集电视剧| 91久久久久久国产精品| 久色乳综合思思在线视频| 日韩成人在线观看| 亚洲网址你懂得| 中文字幕一区电影| 亚洲国产天堂久久国产91| 国产精品a久久久久久| 97在线观看免费高清| 成人妇女淫片aaaa视频| 亚洲成人av在线播放| 欧美视频在线视频| 成人日韩在线电影| 97超碰蝌蚪网人人做人人爽| 国产视频久久久久| 日韩精品中文字| 国产一区二区三区在线| 日韩电影视频免费| 日韩在线视频中文字幕| 中文字幕国产亚洲| 色噜噜狠狠色综合网图区| 日韩中文在线观看| 日韩视频一区在线| 欧美精品久久一区二区| 国内精品久久久久影院优| 国产一区二区久久精品| 成人网欧美在线视频| 在线视频欧美日韩| 日本一区二三区好的精华液| 欧美日韩一区二区精品| 日韩成人在线观看| 欧美中文字幕在线| 奇米四色中文综合久久| 国产精品www色诱视频| 性色av一区二区三区| 8x海外华人永久免费日韩内陆视频| 九九热精品在线| 久久人91精品久久久久久不卡| 国产精品久在线观看| 国产拍精品一二三| 欧美成人精品在线播放| 亚洲级视频在线观看免费1级| 欧美性猛交xxxx黑人| 国外色69视频在线观看| 亚洲一区二区免费在线| 国产一区二区三区高清在线观看| 精品国产一区二区三区四区在线观看| 久久乐国产精品| 91国语精品自产拍在线观看性色| 成年人精品视频| 97碰碰碰免费色视频| 91日韩在线视频| 欧美xxxx18性欧美| 日韩在线中文字幕| 国产亚洲一区二区精品| 久久人人爽人人爽人人片av高请| 亚洲免费精彩视频| 神马久久久久久| 国模gogo一区二区大胆私拍| 日韩精品www| 国产成人自拍视频在线观看| 一区二区三区视频观看| 久久久久亚洲精品成人网小说| 欧美在线免费视频| 国产精品18久久久久久首页狼| 国内外成人免费激情在线视频| 亚洲午夜久久久久久久| 国产亚洲精品久久久久久777| 91日本在线视频| 精品视频—区二区三区免费| 欧美疯狂做受xxxx高潮| 日韩高清免费在线| 久久天天躁狠狠躁老女人| 亚洲人成网站777色婷婷| 久久99久国产精品黄毛片入口|