说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

【探秘ES6】系列专栏:模版字符串

HTML文档下载 WORD文档下载 PDF文档下载
新一代JavaScript标准,ES6即将发布。【探秘ES6】系列专栏将一一剖析ES6的诸多新特性,让Web开发者对此有清晰全面的了解。本文为系列的第四篇,带你了解ES6的模版字符串(Template Strings)。

ES6作为新一代JavaScript标准,即将与广大前端开发者见面。为了让大家对ES6的诸多新特性有更深入的了解,Mozilla Web开发者博客推出了《ES6 In Depth》系列文章。CSDN已获授权,将持续对该系列进行翻译,供大家学习借鉴。本文为该系列的第四篇。

前两次学习了生成器和迭代器以后,脑袋有没有一团浆糊?哈哈。我承诺过本次我们将学习一些简单的东西。

那我们现在就开始吧!

“小句号”的基本使用

ES6新引入了一种新的字符串语法——模版字符串(Template Strings),它看起来和普通的字符串很像,区别在于它不是由单引号'或者双引号"来闭合,而是使用`(俗称:小句号)。我们来看个最简单的例子,它们其实就是字符串而已:

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的变量值来替换字符串的模版替换位。最后生成的字符串为:User jorendorff is not authorized to do hockey(你可以自己试试,我可没忽悠你)。

目前为止,它只是个比+(加号连接符)在语法上略微美观一些而已,你可能想了解更多关于它的细节:

  • 模版替换位中的代码可以是任何JavaScript的表达式,比如函数调用、算数运算等等都是允许的(只要你乐意,你甚至可以在模版字符串中嵌套模版字符串,有种模版中的《盗梦空间》的感觉)。
  • 如果插入的值不是字符串,它将被转换为字符串。例如,如果action是个对象,它的.toString()方法将会被调用。
  • 如果你的模版字符串中包含 ` (小句号),需要使用转义字符`\``,效果相当于 "`"。
  • 举一反三,如果你的模版字符串中需要 ${ 这两个字符,我不想去关心你为什么要这么写,但是你可以使用转义其中任意一个字符:`write \${  或者 $\{`。

与普通字符串不同的是,模版字符串可以写成多行:

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

在模版字符串中,所有空格、换行、缩进都是逐字输出的。

好的,就像我上篇文章所承诺的,我觉得我必须对你大脑的健康负责。所以给一个小小的警告:接下来的内容就比较费脑一点了。你可以现在就放弃阅读,喝杯咖啡享受一下,放松一下大脑。认真地说,不用为放弃下面的内容而感到羞愧噢。 当Lopes Gonçalves穿过了赤道,证明了不会被可怕的海怪吃掉或掉进地球的尽头,然后他还需要去航行整个完整的南半球来增加论证吗?不需要!他返航了,回到家吃了顿美美的午餐。换做是你也会这么做,对不对?

深入讨论“小句号”

我们来讨论一些模版字符串的局限性。

  • 它不会为你自动转义关键字。为了防止脚本注入,你需要认真小心对待那些不受信任的数据,就像你曾经小心地拼接字符串一样。
  • 它并没有明确地说明如何配合国际化库(一个针对用户所处的国家/语言不同来国际化你的代码的库)来使用。模版字符串不会处理特定语言的数字、日期等的格式化。
  • 它并不能代替像Mustache、Nunjucks这样的模板库。

模版字符串没有内置针对循环的语法——通过数组来循环生成一个HTML表格;甚至条件语句也不支持。(当然,你可以使用模版嵌套来实现,但是这样的方法太笨拙,我认为不可取。)

ES6在模版字符串中为JS开发者和库设计人员提供了一种解决方案来帮助他们处理这些局限性问题。这个特性被称做模版标记。

模版标记的语法很简单。我们只需要在“小句号”的前面加一个额外的标记。在我们接下来的第一个例子中,SaferHTML就是它的标记,我们使用这个标记来处理上面列表中的第一个局限性问题:自动转义关键字。

必须清楚SaferHTML并不是ES6标准库中的内容。在下面我们将会自己来实现它。

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

这里使用了一个标识符SaferHTML来作为标记,标记也可以是一个属性——SaferHTML.escape,甚至可以是一个函数调用——SaferHTML.escape({unicodeControlCharacters: false})。(说明一下,任何ES6的MemberExpressio类或CallExpression类都可以作为标记使用)。

可以看出不含标记的模版字符串适用于简单的字符串拼接。标记模版完全适用于其它场景:如函数调用。

上面的代码与这段等效:

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

templateData 是由模版的字符串部分所组成的不可变数组,由JS引擎为我们提供。下面是一个拥有两个元素的数组,因为在标记模板中他们被模版替换所分割,有两个字符串部分。所以templateData 应该是这个样子的: Object.freeze(["<p>", " has sent you a bonk.</p>"]。

(实际上templateData 还有一个属性。我并不打算在这篇文章中用到它,为了完整性我还是提一下: templateData.raw 是另一个囊括了标记模版中所有字符串部分的数组,它的源码就和它的名称(raw)一样原始——还保留着\n这样的转义序列,而不是被转到新的一行等。标准的String.raw使用了最原始的字符串。)

这样就给了SaferHTML函数很大的自由度,可以用很多可选的方法去解析字符串和替换字符。

现在你一定想弄清楚SaferHTML究竟是怎么实现的,或许你想亲手来尝试实现它。它终究只是个函数而已。你可以再Firefox的控制台中测试一下。

下面是其中一种方式(查看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, "&")            .replace(/</g, "<")            .replace(/>/g, ">");    // Don't escape special characters in the template.    s += templateData[i];  }  return s;}

定义了这个方法以后,SaferHTML`<p>${bonk.sender} has sent you a bonk.</p>`将会被解析为 "<p>ES6&lt;3er has sent you a bonk.</p>"。那么你的用户传入的值都是安全的,即使有人恶意地将bonk.sender 赋值为 "Hacker Steve <script>alert('xss');</script>",返回的也是不可执行的字符串,无论这段字符串的含义是什么,都不会有安全漏洞。

(顺便说一句,如果你觉得函数使用参数对象的方式让你感觉这样很笨重,我们下次将换用另一种方法。ES6还有另一个我认为你会喜欢的新特性。)

一个例子并不能说明标记模版的灵活性。让我们再来看看我们能为之前列出的那些模版字符串的局限性做些什么改进。

  • 模版字符串不自动转义特殊字符。但是我们已经看到了,使用标记模版我们就能解决这个问题。实际上,我们能做得更好。

从安全性的角度来看,我的SaferHTML函数功能性非常弱。HTML中不同的地方有不同的关键字需要不同的转义方式。SaferHTML把它们全部都转义,但是我们可以再付出一些努力把SaferHTML写的更精明一点,完全按照字节来解析templateData中的字符串,这样我们就知道哪些替换位是在纯HTML中;哪些是在元素属性中,这些 ‘ 和 “ 就需要转义;那些在URL查询字符串中需要使用URL转义而不是HTML转义等等。它可以准确地对每个替代位进行正确的转义。

也许你会有疑问——HTML解析效率低,这方法是不是很牵强?幸运的是标记模版的字符串部分是固定不变的。SaferHTML可以将这部分的解析结果缓存起来,这样就可以提高运行速度了。(这个缓存可以是一个WeakMap,WeakMap是ES6的新特性,我们在以后的文章中将会对它有所讨论。)

  • 模版字符串没有涉及国际化相关的特性。好在有了标记,这个问题就迎刃而解。Jack Hsu发表了一篇博客为我们迈出了这第一步。下面是一个例子:

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是JavaScript,但是这里有一个我们不熟悉的语句——:c(CAD),Jack把它放到了模板的字符串部分。JavaScript理所当然由JavaScript引擎来处理,而字符串部分则有Jack的i18n标记来处理。我们可以从i18n的文档中知道:c(CAD)表示加拿大元,那么amount则表示了加拿大元的数额。

这就是标记模板的作用了。

  • 它并不能代替像Mustache 、Nunjucks这样的模板库,大部分原因是因为它没有内置对循环和条件句的支持。那么现在我们一起来看看如何解决这个问题,准备好了吗?

如果JS没有为我们提供某个特性,那我们就自己写一个!

// 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>`;

它的灵活性还不止于此。记住,标记函数的参数不会自动转换为字符串。它的返回值也是这样,它们可以是任何类型,标记模版不一定是字符串!你可以使用自定义标签来创建自定义正则表达式、DOM树、图片、完整的异步流程、JS数据结构、GL着色器等等。

标记模版鼓励库开发人员去创建强大的基于特定领域的语言。这些语言看起来一点也不像JS,但是他们可以无缝地嵌入JS中并且可以智能地与其它语言进行交互。现在,我想不出其它任何有类似特性的语言,我不知道这个特性将来会给我们的开发带来什么改变,但这个改变应该是令人惊喜的。

我什么时候可以开始使用模版字符串?

在服务端,io.js已经开始支持模版字符串了。

浏览器里,FireFox 34+已经支持模版字符串。去年夏天Guptha Rajagopal已经把它作为一个实习项目。Chrome 41+也支持模板字符串,IE和Safari不支持。现在,如果你想在web项目中使用模版字符串你需要用到Babel或Traceur来支持;你也可以在TypeScript中使用。

在Markdown中可以使用吗?

嗯? 

哦……这是一个好问题。

(这一部分与JavaScript无关。如果你不使用Markdown,可以跳过这一段。)

Markdown和JavaScript都使用 ` 来作为模版字符串的特殊字符。实际上,在Markdown中

它是内联文本的定界符。

如果你在Markdown中用下面的方式来写是会有问题的:

To display a message, write `alert(`hello world!`)`.

显示的结果为:

To display a message, write alert(hello world!).

请注意,在输出中是不会有小句号的。Markdown把这个四个小句号都解释为定界符,在输出结果中被HTML标记替换掉了。

为了避免这种情况,我们一开始在Markdown就采用了一种比较少见的特性:使用多重小句号来作为代码定界符,如下:

To display a message, write ``alert(`hello world!`)``.

可以到Gist上去查看更多细节,它是由Markdown写的,你可以查看源码。

下期预告

下篇文章,我们将学习两个新特性,在其它语言中这两个特性已经被程序员们愉快地使用了几十年了:其中一个是为了那些喜欢尽量避免使用参数的开发人员准备的,另一个是给那些喜欢使用很多参数的人准备的。当然,两种特性都为我们提供了,我们可以根据个人对函数的使用习惯来选择。

这些特性可以直接在Firefox中测试,所以下次我们一起来试一下吧,我们的客座来宾Benjamin Peterson将为大家讲解ES6的default parameters和rest parameters。(译者:向渝 责编:陈秋歌)

原文链接:ES6 In Depth: Template strings

本译文遵循Creative Commons Attribution Share-Alike License v3.0 

相关阅读:

【探秘ES6】系列专栏:ES6简介

【探秘ES6】系列专栏:迭代器和for-of循环

【探秘ES6】系列专栏:生成器

欢迎加入CSDN前端交流群:218126086,进行前端技术交流。  

King.com和Halfbrick Studios成功背后的21款工具 五大实用技巧 帮设计师实现高效会议沟通 机遇与挑战并存 Testin进军众测 新增多SIM卡API,Android 5.1 SDK正式发布! 谷歌代码托管平台Google Code将正式关闭 提升Sketch使用效率的6个实用技巧 界面设计原则之一篇:权衡优先级 突出焦点 划分好内容层级 开源的ResearchKit:苹果将如何颠覆未来医疗? CocoaPods 0.36正式发布,实现Swift和iOS 8动态框架支持 C++入门学习书籍推荐 GitHub是如何征服Google、微软和其它公司的 约见越狱大神!2015 MSS移动安全峰会议程披露 Spark 1.3更新概述:176个贡献者,1000+ patches 从游戏设计到星际探险,微软HoloLens全息技术将改变什么? 触摸屏技术未来?详解Apple新手段Force Touch 专访云适配CEO陈本峰:紧跟HTML5热潮,Web组件化知多少? QQ音乐5.0全新设计过程要点解析 GDC 2015感悟:从0到1,VR投入手游开发路漫漫 TestBird发布手游真人众测平台——附中国手游兼容性测试白皮书 与用户的再一次连接,微软的免费升级计划背后 颠覆App!LayaBox用Flash开发重度HTML5游戏 WinHEC:微软小娜与小冰正式登陆Windows 10平台 Coursera工程师董飞:典型硅谷公司大数据实战分析 微软开源Visual Studio构建工具MSBuild 死而复生!下架6月,Launcher重回App Store 虚拟投影、高保真耳机!新型可穿戴家庭影院Dashbon Mask 【程序员电子刊精选】躺枪的互联网思维 Algolia的分布式搜索网络架构 对抗苹果?豪雅联合Google、Intel开发智能奢表 VR产品技术解析之三星Gear VR 雅虎北研即将关闭 人才抢夺战迅速拉响 为什么要学Java 看 http://Scjp.myrice.com 也许你的一切会改变! 回答问题,我给500分!! 语音聊天用什么软件好?qq,netmeeting,yahoo message or icq? 为什么不能汇编成功? 各位,帮我一下,非赏急! 数据库快照复制问题,总出错,求救!(50分) 请问这是怎么一回事。win2k(p)+tomcat+jdk1.4.` 在VB中怎样设置Excel单元格的样式?如设置为百分数显示单元格数值? 下拉菜单问题? 请问这是怎么一回事。win2k(p)+tomcat+jdk1.4.` 求救,我财务系统的问题,大大们一定要帮助我呀! 我在调试jsp是的一个错误信息,请指教~~~ 急!!! 一个烦人的问题 关于在应用程序中使用dll中资源的问题 關於並行執行的問題 也许你现在就会改变!! 看 http://Scjp.myrice.com 为什么要学Java 其实我们很封闭! 关于NT的小问题! 请问: 請問哪里有c++的書籍下載? 几个控件重叠在一起,怎样用代码的方式使其中的某个控件在运行时放至最上!?谢! 也许你现在就会改变!! 看 http://Scjp.myrice.com 其实我们很封闭! 如何发布我的网站? 怎样编程在Windows开始菜单的的“启动”栏中添加本程序的快捷方式? 谁有installshield 6.30的license注册文件? 请问:DataGrid在WebForm中明明有数据显示,但用浏览器看就没,为何? 显卡选择问题 ? 也许你现在就会改变!! 看http://Scjp.myrice.com 其实我们很封闭! 一个Acme .....???? 共计350分哟。急急。。。。我在PHP区有发言。但是还连不上SQL SERVER2000呀。。请进 boyqing(阿清):我的问题转到这了! 谁有installshield 6.30的license注册文件? 高手请进! 大家用java都来做什么????? 搞linux,unix底层的在中关村有没有搞头? 请问为什么我的CBuilder中在菜单项File/new下的无法找到RemoteDataModule?我是新手,请帮忙! 这几句TSQL有错?帮忙看看 请教关于网卡与声卡冲突的处理方法 谁有installshield 6.30的license注册文件? 请问如何在页面操作中保存dataset 怎样选定ListCtrl中的一行(包括subItem区域)? 类对象的实例和类的实例有什么区别?? 请问各位大虾,公文管理系统怎么做? 如何将TIF或TIFF文件转换成网页可以显示的JPG,或是GIF文件(最好给出JAR和例子) 这段程序应该怎么编? 各位老大,近来看看吧,一下午了也没有人来回答,苦命呀!加分...狂加....跳楼... TO net_lover(孟子E章) : 在datagrid中如何在获得当前字段内的内容? 高手都过来,这里有好几个问题!!! 安全队列问题?up有分! 如何在XML文件中獲得某個節點下重復的節點的個數﹐用IXMLNodeCollectionMA嗎? “天下相亲与相爱“,这句歌词是哪首歌的? 6只兔,3只牛,2只狗,3只猪,4只鸭. 蝗虫生活在干燥的环境中,它的呼吸器官是 求曲线ρ^2=cos2θ所围成图形的面积 为什么说人类第一次登月是人类探索太空的里程碑 蝗虫适应干旱环境的原因如题 求曲线r^2=cos2θ所围成图形的面积 答案1/2, 若sin2α+2sin2β=2cosα,y=sin2α+cos2β的最大值为M,最小值为m.求M+m.2α和2β均为平方α、β 描写蓝天的诗(现代诗、古诗都可以)、歌词或好的句子、段落是<蓝>天!只要是写蓝天的句子或诗就行 要一片五年级动物的说明文(300字左右) 为什么说人类第一次登月对整个人类来说是巨大的飞跃,是人类探索太空的里程碑 蝗虫生活在干燥的环境中,防止水分散失的结构是( )A,肺 B,气管 C,气囊 D,外骨骼 (2sin2α/1+cos2α)*(cosα)^2/cos2α=多少 :求证:(1-2sinθcosθ)/(cos2θ-sin2θ)=(cos2θ-sin2θ)/(1+2sinθcosθ).求证:(1-2sinθcosθ)/(cos2θ-sin2θ)=(cos2θ-sin2θ)/(1+2sinθcosθ).cos2θ指的是cos^2θ~对的 没抄错 你认为哪里错了? 关于鱼体内的寄生虫问题现在菜市场里有一些卖鱼的人经常把自己从河里用电网打捞上来的鱼拿出来卖.我的妈妈很喜欢买这样的小鲫鱼,又便宜又好吃.可是现在河水污染严重,很多鱼的体内都 像相亲相爱的词语还有什么? 谈一下人类第一次登月成为人类探索太空里程碑的意义 急用 都什么鱼有寄生虫?怎样才能杀死?吃了对人体有什么危害? (2sin2α/1+cos2α)*(cos^2/cos2α)=? 2sinα=cosα,求cos2α+sin2α+1/cos^2 α 已知曲线C的参数方程为x=2cosθ y=3sinθ θ为参数,0≤θ 小学一年级语文上册组词一上上的什么? 同班同学情同手足怎么能打架斗殴呢?这时你会说诗句----- 初一上册第19课课后第一大题 登月过程示意图怎么画 情同手足中的手足是什么意思,还有面目用来比喻什么这可是送分啊 已知tanΘ=1/3,求cos2Θ+2sin2Θ 关于月球,登月 探索太空的事例内容越具体越好。 情同手足中手足一词比喻什么? 化简 [2sin2α/(1+cos2α)]*[cos^2α/cos2α] 蝗虫的足翅触角各有什么特点 求解 小学二年级语文题什么字可以和这几个字组成词:‘日、星、间、求’ 2sin2α/1+cos2α 乘以 cos²α/cos2α,本人比较笨希望讲细一点,一步一步的. 蝴蝶破茧而出的优美语句给积分! 下面的句子用什么词形容?小学二年级的语文题下面的句子用什么词形容?第1题:在极短的时间内发生的,出乎意料.第2题:重视,爱护,常放在心上.第3题:亲密,热情.第4题:使不存在,除去. 自从上次赛跑乌龟大胜兔子后,乌龟便成了体育界的名人,又是广告,又是讲演,活动不断.可蚂蚁便便不服气,向乌龟下了挑战书,我们来看:乌龟先生:本日20日下午,我们进行长跑,从小柳树开始 比较蝶类、金龟甲、蛾类、蝇类、蝗虫、蝽象、蜂类、蝼蛄、螳螂、步甲、蜜蜂等触角、足、翅的类型. 小学二年级语文第三课三组词龙字怎么组词 兔子,乌龟,蚂蚁,蜗牛,老鼠,龙它们几个哪个跑得快? 关于蝴蝶的句子 要优美,又有忧伤的感觉就像言情小说里描写的忧伤 一、照样子写词语:急得(团团转)做得( ) 热得( ) 笑得( ) 酸得( ) 谈得( )二、把下面的词语补充完整( )不林( )轻重倒置 人教版七年级下语文书第五课课后题最后一题是什么 蝗虫的翅的特征是什么 二年级语文词语 七年级上册语文书第六课课后题答案 关于蝴蝶的美丽的句子我需要:1、诗句2、赞美的句子3、类似散文的抒情句 照样子给下列词语扩词.(每词3个)例:清秀——山清水秀风雨—— 昏暗—— 曲线r=√2sinθ含在曲线r∧2=cos2θ内部的部分的曲线之长是?答案√2pai/3求详解. 蝗虫有几对翅? 关于自然万物的相依相伴,相亲相爱的和谐状态的诗句并说明理由 2只鸭子可换4 只羊,3 只羊可换6 只兔子,3 只鸭子可换几只兔子? 蝴蝶优美的诗句 不许组菠萝要三个 两只鸭换四只羊3只羊换6只兔子,问三只鸭换几只兔 有关蝴蝶的优美句子 反对相亲 经典语句 3年级下才数学题2只鸭子可换4只羊3只羊可换6只兔子3只鸭子可换几只兔子怎样列式 如图,桌子上有四分之三杯水,小健喝掉三分之一,想把水加满,他拿起另一杯盛满水的杯子向第一个杯子倒结果不小心,加满溢出来后他才发现,这时第二杯水只剩下四分之一,那么溢出的水到底是 例:清秀——山清水秀要4个 2只鸡可以换3只鸭,4只兔可以2只鸭,1只鸡可以换几只兔?这道题有几种算法? 如下图,桌子上有四分之三杯水,小健喝掉三分之满水的杯子向第一个杯子倒结果不小心,加满溢出来后他才发现
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘