什么是模板字符串
JavaScript 中,模板字符串是在 ECMAScript2015 中加入的新语法。
它以反引号(`)替代普通字符串的单引号、双引号,允许在内部使用特定语法(${...})嵌入表达式,同时它还支持多行字符串。
以上功能基本稍有了解的应该都知道并使用过了,但是模板字符串还有一个特性:带标签的模板字符串。
如果一个模板字符串前面是一个表达式(通常是一个函数),该字符串就被称为 带标签的模板字符串。它会在模板字符串处理后被调用。
基本语法
创建一个字符串变量
1 2 3 4 5 6
   |  var single = 'this is a single-quote string'; var double = "this is a double-quote string";
 
  var template = `this is a template string`;
 
  | 
 
如果要插入一个变量的话
1 2 3 4 5
   |  var str1 = '1 + 2 = ' + (1 + 2);
 
  var str2 = `1 + 2 = ${1 + 2}`;
 
  | 
 
如果要在字符串内换行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   |  var str3 = 'string line 1\n' +            'string line 2';
 
 
 
  var str4 = `string line 1 string line 2`; 
 
 
 
  var str5 = `string line 1             string line 2`;
 
 
 
  | 
 
带标签的模板字符串
更高级形式的模板字符串是带标签的模板字符串。标签使得你可以用函数来解析模板字符串。标签函数的第一个参数是通过占位符分割后的字符串数组,剩余参数为占位符中表达式的返回值。你可以根据需要在函数中返回处理好的字符串,或者一个完全不同的数据类型:一个新的函数、对象、其他的字符串、布尔值……所有 JavaScript 支持的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   | var age = 16; function myTag(templateStrings, age) {   var str0 = templateStrings[0];   var ageStr = '';   if (age < 18) {     ageStr = 'juvenile';   } else {     ageStr = 'adult';   }   return str0 + ageStr; }
  myTag`That guy is ${age}`; 
 
 
  function template(strings, ...keys) {   return (function(...values) {     var dict = values[values.length - 1] || {};     var result = [strings[0]];     keys.forEach(function(key, i) {       var value = Number.isInteger(key) ? values[key] : dict[key];       result.push(value, strings[i + 1]);     });     return result.join('');   }); }
  var t1Closure = template`${0}${1}${0}!`; t1Closure('Y', 'A');   var t2Closure = template`${0} ${'foo'}!`; t2Closure('Hello', {foo: 'World'});  
   | 
 
模板字面量及转义序列
自 ES2016 开始,模板字面量遵循以下转义序列的规则:
- Unicode 字符以 
\u 开头,例如:\u00A9 
- Unicode 码位以 
\u{} 表示,例如:\u{2F804} 
- 十六进制以 
\x 开头,例如:\xA9 
- 八进制以 
\ 和数字开头,例如:\251 
据此规则,可以得出以下表达式是有问题的,因为对于每一个 ECMAScript 语法,解析器都会去查找有效的转义序列,但是只能得到这是一个形式错误的语法:
1 2 3 4 5 6 7
   | myTag`\unicode`;
 
 
 
 
  `\unicode`; 
   | 
 
虽然在 ES2018 中移除了在带标签的模板字面量中对转义序列的语法限制,但是非法转义序列仍然可以在标签函数得到的参数中体现出来。
1 2 3 4 5 6
   | function latex(strings) {   return { cooked: strings[0], raw: strings.raw[0] } }
  latex`\unicode`;
 
  | 
 
由此我们又引出了一个新的属性:raw
原始字符串
标签函数的第一个参数中,存在着一个特殊的属性 raw,我们可以访问模板字符串中的原始字符串,而不经过特殊字符的替换。
1 2 3 4 5 6 7 8 9 10
   | function tag(strings) {   console.log(strings.raw); }
  var one = 1; var two = 2;
  tag`string line ${one} \n string line ${two}`
 
 
  | 
 
另外,使用 String.raw() 方法创建原始字符串和使用默认模板函数和字符串连接创建是一样的。
1 2 3 4
   | var str = String.raw`Hey\nYang`; str.length;  str === 'Hey\nYang';  str === 'Hey\\nYang'; 
   | 
 
参考资料