前面的话

  JS 的字符串相对其他语言来说功能总是有限的,事实上,ES5中一直缺乏许多特性,如多行字符串、字符串格式化、HTML转义等。ES6通过模板字面量的方式进行了填补,模板字面量试着跳出JS已有的字符串体系,通过一些全新的方法来解决类似的问题。本文将详细介绍ES6模板字面量

基本用法

  模板字面量是增强版的字符串,它用反引号(`)标识

  1. let message = `Hello world!`;
  2. console.log(message); // "Hello world!"
  3. console.log(typeof message); // "string"
  4. console.log(message.length); //

   以上代码中,使用模板字面量语法创建一个字符串,并赋值给message变量,这时变量的值与一个普通的字符串无异

  如果想在字符串中包含反引号,只需使用反斜杠( \ )转义即可

  1. let message = `\`Hello\` world!`;
  2. console.log(message); // "`Hello` world!"
  3. console.log(typeof message); // "string"
  4. console.log(message.length); //

多行字符串

  自javascript诞生起,开发者们就一直在寻找一种能创建多行字符串的方法。如果使用双引号或单引号,字符串一定要在同一行才行

【反斜杠】

  由于javascript长期以来一直存在一个语法bug,在换行之前的反斜线( \ )可以承接下一行的代码,于是可以利用这个bug来创建多行字符串

  1. var message = "Multiline \
  2. string";
  3. console.log(message); // "Multiline string"

  message 字符串打印输出时不会有换行,因为反斜线被视为延续符号而不是新行的符号。为了在输出中显示换行,需要手动加入换行符

  1. var message = "Multiline \n\
  2. string";
  3. // "Multiline
  4. // string"
  5. console.log(message);

  在所有主流的 JS 引擎中,此代码都会输出两行,但是该行为被认定为一个 bug ,并且许多开发者都建议应避免这么做

  在ES6之前,通常都依靠数组或字符串的拼接来创建多行字符串

  1. var message = ["Multiline ","string"].join("\n");
  2. let message = "Multiline \n" +"string";

  JS一直以来都不支持多行字符串,开发者的种种解决方法都不够完美

【反引号】

  ES6 的模板字面量使多行字符串更易创建,因为它不需要特殊的语法,只需在想要的位置直接换行即可,此处的换行会同步出现在结果中

  1. let message = `Multiline
  2. string`;
  3. // "Multiline
  4. // string"
  5. console.log(message);
  6. console.log(message.length); //

  在反引号之内的所有空白符都是字符串的一部分,因此需要特别留意缩进

  1. let message = `Multiline
  2. string`;
  3. // "Multiline
  4. // string"
  5. console.log(message);
  6. console.log(message.length); //

  以上代码中,模板字面量第二行前面的所有空白符都被视为字符串自身的一部分

  如果一定要通过适当的缩进来对齐文本,可以考虑在多行模板字面量的第一行空置并在后面的几行缩进

  1. let html = `
  2. <div>
  3. <h1>Title</h1>
  4. </div>`.trim();

  以上代码中,模板字面量的第一行没有任何文本,第二行才有内容。 HTML标签的缩进增强了可读性,之后再调用trim()方法移除了起始的空行

  当然,也可以在模板字面量中使用 \n 来指示换行的插入位置

  1. let message = `Multiline\nstring`;
  2. // "Multiline
  3. // string"
  4. console.log(message);
  5. console.log(message.length); //

变量占位符

  模板字面量看上去仅仅是普通JS字符串的升级版,但二者之间真正的区别在于模板字面量的变量占位符。变量占位符允许将任何有效的JS表达式嵌入到模板字面量中,并将其结果输出为字符串的一部分

  变量占位符由起始的 ${ 与结束的 } 来界定,之间允许放入任意的 JS 表达式。最简单的变量占位符允许将本地变量直接嵌入到结果字符串中

  1. let name = "Nicholas",
  2. message = `Hello, ${name}.`;
  3. console.log(message); // "Hello, Nicholas."

  占位符 ${name} 会访问本地变量 name ,并将其值插入到 message 字符串中。 message变量会立即保留该占位符的结果

  既然占位符是JS表达式,那么可替换的就不仅仅是简单的变量名。可以轻易嵌入运算符、函数调用等

  1. let count = 10,
  2. price = 0.25,
  3. message = `${count} items cost $${(count * price).toFixed(2)}.`;
  4. console.log(message); // "10 items cost $2.50."
  1. function fn() {
  2. return "Hello World";
  3. }
  4.  
  5. `foo ${fn()} bar`
  6. // foo Hello World bar

  模板字面量本身也是 JS 表达式,因此可以将模板字面量嵌入到另一个模板字面量内部

  1. let name = "Nicholas",
  2. message = `Hello, ${
  3. `my name is ${ name }`
  4. }.`;
  5. console.log(message); // "Hello, my name is Nicholas."

标签模板

  模板字面量真正的威力来自于标签模板,每个模板标签都可以执行模板字面量上的转换并返回最终的字符串值。标签指的是在模板字面量第一个反引号'`'前方标注的字符串

  1. let message = tag`Hello world`;

  在这个示例中, tag 就是应用到 `Hello world` 模板字面量上的模板标签

【定义标签】

  标签可以是一个函数,调用时传入加工过的模板字面量各部分数据,但必须结合每个部分来创建结果。第一个参数是一个数组,包含Javascript解释过后的字面量字符串,它之后的所有参数都是每一个占位符的解释值

  标签函数通常使用不定参数特性来定义占位符,从而简化数据处理的过程

  1. function tag(literals, ...substitutions) {
  2. // 返回一个字符串
  3. }

  为了进一步理解传递给tag函数的参数,查看以下代码

  1. let count = 10,
  2. price = 0.25,
  3. message = passthru`${count} items cost $${(count * price).toFixed(2)}.`;

  如果有一个名为passthru()的函数,那么作为一个模板字面量标签,它会接受3个参数首先是一个literals数组,包含以下元素

  1、第一个占位符前的空字符串("")

  2、第一、二个占位符之间的字符串(" items cost $")

  3、第二个占位符后的字符串(".")

  下一个参数是变量count的解释值,传参为10,它也成为了substitutions数组里的第一个元素

  最后一个参数是(count*price).toFixed(2)的解释值,传参为2.50,它是substitutions数组里的第二个元素

  [注意]literals里的第一个元素是一个空字符串,这确保了literals[0]总是字符串的始端,就像literals[literals.length-1]总是字符串的结尾一样。substitutions的数量总比literals少一个,这也意味着表达式substitutions. Iength === literals. Iength-1的结果总为true

  1. var a = 5;
  2. var b = 10;
  3.  
  4. tag`Hello ${ a + b } world ${ a * b }`;
  5. // 等同于
  6. tag(['Hello ', ' world ', ''], 15, 50);

  通过这种模式,我们可以将literals和substitutions两个数组交织在一起重组结果字符串。先取出literals中的首个元素,再取出substitution中的首个元素,然后交替继续取出每一个元素,直到字符串拼接完成。于是可以通过从两个数组中交替取值的方式模拟模板字面量的默认行为

  1. function passthru(literals, ...substitutions) {
  2. let result = "";
  3. // 仅使用 substitution 的元素数量来进行循环
  4. for (let i = 0; i < substitutions.length; i++) {
  5. result += literals[i];
  6. result += substitutions[i];
  7. }
  8. // 添加最后一个字面量
  9. result += literals[literals.length - 1];
  10. return result;
  11. }
  12. let count = 10,
  13. price = 0.25,
  14. message = passthru`${count} items cost $${(count * price).toFixed(2)}.`;
  15. console.log(message); // "10 items cost $2.50."

  这个示例定义了一个passthru标签,模拟模板字面量的默认行为,展示了一次转换过程。此处的小窍门是使用substitutions.length来为循环计数

【应用】

  “标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容

  1. var message =
  2. SaferHTML`<p>${sender} has sent you a message.</p>`;
  3.  
  4. function SaferHTML(templateData) {
  5. var s = templateData[0];
  6. for (var i = 1; i < arguments.length; i++) {
  7. var arg = String(arguments[i]);
  8.  
  9. // Escape special characters in the substitution.
  10. s += arg.replace(/&/g, "&amp;")
  11. .replace(/</g, "&lt;")
  12. .replace(/>/g, "&gt;");
  13.  
  14. // Don't escape special characters in the template.
  15. s += templateData[i];
  16. }
  17. return s;
  18. }

  上面代码中,sender变量往往是用户提供的,经过SaferHTML函数处理,里面的特殊字符都会被转义

  1. var sender = '<script>alert("abc")</script>'; // 恶意代码
  2. var message = SaferHTML`<p>${sender} has sent you a message.</p>`;
  3.  
  4. console.log(message);// <p>&lt;script&gt;alert("abc")&lt;/script&gt; has sent you a message.</p>

  标签模板的另一个应用,就是多语言转换(国际化处理)

  1. i18n`Welcome to ${siteName}, you are visitor number ${visitorNumber}!`
  2. // "欢迎访问xxx,您是第xxxx位访问者!"

  模板字符串本身并不能取代模板引擎,因为没有条件判断和循环处理功能,但是通过标签函数,可以自己添加这些功能

  1. // 下面的hashTemplate函数
  2. // 是一个自定义的模板处理函数
  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. `;

raw()

  String.raw方法,往往用来充当模板字面量的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,对应于替换变量后的模板字面量

  1. let message1 = `Multiline\nstring`,
  2. message2 = String.raw`Multiline\nstring`;
  3. console.log(message1); // "Multiline
  4. // string"
  5. console.log(message2); // "Multiline\\nstring"
  1. String.raw`Hi\n${2+3}!`;
  2. // "Hi\\n5!"
  3.  
  4. String.raw`Hi\u000A!`;
  5. // 'Hi\\u000A!'

  如果原字符串的斜杠已经转义,那么String.raw不会做任何处理

  1. String.raw`Hi\\n`// "Hi\\n"

  String.raw方法可以作为处理模板字面量的基本方法,它会将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用。

  String.raw方法也可以作为正常的函数使用。这时,它的第一个参数,应该是一个具有raw属性的对象,且raw属性的值应该是一个数组

  1. String.raw({ raw: 'test' }, 0, 1, 2);// 't0e1s2t'
  2.  
  3. // 等同于
  4. String.raw({ raw: ['t','e','s','t'] }, 0, 1, 2);

ES6模板字面量的更多相关文章

  1. ES6 模板字面量

    模板字面量 解决的问题 1.多行字符串 一个正式的多行字符串的概念 2.基本的字符串格式化 将变量的值嵌入字符串的能力 3.HTML转义 向HTML插入安全转换后的字符串的能力 (1)基础语法 相当于 ...

  2. ES6入门四:对象字面量扩展与字符串模板字面量

    简洁属性与简洁方法 计算属性名与[[prototype]] super对象(暂时保留解析) 模板字面量(模板字符串) 一.简洁属性与简洁方法 ES6中为了不断优化代码,减低代码的耦合度在语法上下了很大 ...

  3. ES6躬行记(4)——模板字面量

    模板字面量(Template Literal)是一种能够嵌入表达式的格式化字符串,有别于普通字符串,它使用反引号(`)包裹字符序列,而不是双引号或单引号.模板字面量包含特定形式的占位符(${expre ...

  4. ES6里关于模板字面量的拓展

    JS 的字符串相对其他语言来说功能总是有限的,事实上,ES5中一直缺乏许多特性,如多行字符串.字符串格式化.HTML转义等.ES6通过模板字面量的方式进行了填补,模板字面量试着跳出JS已有的字符串体系 ...

  5. es6对象字面量增强

    相对于ES5,ES6的对象字面量得到了很大程度的增强.这些改进我们可以输入更少的代码同时语法更易于理解.那就一起来看看对象增强的功能.对象字面量简写(Object Literal Shorthand) ...

  6. 学习熟悉箭头函数, 类, 模板字面量, let和const声明

    箭头函数:https://blog.csdn.net/qq_30100043/article/details/53396517 类:https://blog.csdn.net/pcaxb/articl ...

  7. ES6:字面量的增强写法

    以前对象字面量的写法: 属性的增强写法: ES6中可以写成: 方法的增强写法 ES6中可以写成: ~~~~~ END ~~~~~

  8. JS:关于JS字面量及其容易忽略的12个小问题

    简要 问题1:不能使用typeof判断一个null对象的数据类型 问题2:用双等号判断两个一样的变量,可能返回false 问题3:对于非十进制,如果超出了数值范围,则会报错 问题4:JS浮点数并不精确 ...

  9. [译]ES6新特性:八进制和二进制整数字面量

    原文:http://whereswalden.com/2013/08/12/micro-feature-from-es6-now-in-firefox-aurora-and-nightly-binar ...

随机推荐

  1. Linux安装JDK完整步骤

    1.检查一下系统中的jdk版本 [root@localhost software]# java -version 显示: openjdk version "1.8.0_102" O ...

  2. js的函数返回值

    今天从跟公司牛人那学到的~避免以后忘了赶快记录下来 平时JS的function的返回值可以是一个数值,也可以是一个对象({name:abc,age:123}),更可以是一个函数(这里我是第一次听说), ...

  3. 对jsp的初步了解及规范问题(二)

    前言 今天的例子是用jsp制作简单的“艾宾浩斯记忆曲线的学习计划表”. 重点不是算法,重点是学习jsp中的一个重要的思想,作为展现层,jsp中不应该出现业务逻辑代码. 当中<%%>代码也会 ...

  4. mysql字符编码设置

    1.显示当前编码信息 mysql>show variables like '%character%' +--------------------------+------------------ ...

  5. Bash中的数学扩展

    Bash只支持整数运算,不支持浮点运算.如果需要进行浮点运算,需要使用bc程序.Bash中的数学扩展有两种形式:$[ expression ]或$(( expression )) 例子:$echo $ ...

  6. input响应慢问题解决办法

    input[file]标签的accept属性可用于指定上传文件的 MIME类型 . 例如,想要实现默认上传图片文件的代码,代码可如下: <input type="file" ...

  7. Windows定时关机

    用shutdown命令.开始菜单>运行,输入shutdown -s -t 7200 (两个小时之后关机)at 12:00 shutdown -s (12:00关机) 其他设置:shutdown ...

  8. jquery让页面滚动条top,滚动条 顶部

    jquery让页面滚动条top,滚动条 顶部$(document).scrollTop(0);

  9. 框架基础:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码

    距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这个行业,让大脑休息一下.一个人旅行,一个人休息,正好也去完成一个目标 --- 拥有自己的驾照.当然,也把自己晒的黑漆马虎的.不过这一段时间 ...

  10. 【Android Developers Training】 18. 重新创建一个Activity

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...