Template literals

Template literals

句法

`string text` `string text line 1 string text line 2` `string text ${expression} string text` tag `string text ${expression} string text`

描述

模板字符串使用反引号 (` `) 来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法(${expression})的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来,如果一个模板字符串由表达式开头,则该字符串被称为带标签的模板字符串,该表达式通常是一个函数,它会在模板字符串处理后被调用,在输出最终结果前,你都可以通过该函数来对模板字符串进行操作处理。在模版字符串内使用反引号(`)时,需要在它前面加转义符(\)。

`\`` === '`' // --> true

多行字符串

在新行中插入的任何字符都是模板字符串中的一部分,使用普通字符串,你可以通过以下的方式获得多行字符串:

console.log('string text line 1\n' + 'string text line 2' // "string text line 1 // string text line 2"

要获得同样效果的多行字符串,只需使用如下代码:

console.log(`string text line 1 string text line 2` // "string text line 1 // string text line 2"

表达式插补

在普通字符串中嵌入表达式,必须使用如下语法:

var a = 5; var b = 10; console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.' // "Fifteen is 15 and // not 20."

现在通过模板字符串,我们可以使用一种更优雅的方式来表示:

var a = 5; var b = 10; console.log(`Fifteen is ${a + b} and not ${2 * a + b}.` // "Fifteen is 15 and // not 20."

嵌套模板

在某些时候,嵌套模板是最简单也是更可读的方式来配置字符串。在一个被抽出的模板中,简单地通过${( )}在模板中添加括号来允许内部反引号。例如,如果条件是真的,那么返回这个模板化的文字。

In ES5:

var classes = 'header' classes += (isLargeScreen() ?   '' : item.isCollapsed ?   ' icon-expander' : ' icon-collapser'

在ES2015中使用模板文字而不嵌套:

const classes = `header ${ isLargeScreen() && item.isCollapsed ?   'icon-expander' : 'icon-collapser' }`;

In ES2015 with nested template literals:

const classes = `header ${( isLargeScreen() &&  `icon-${item.isCollapsed ? 'expander' : 'collapser'}`)}`;

标记模板文字

A more advanced form of template literals are tagged template literals. Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions. In the end, your function can return your manipulated string (or it can return something completely different as described in the next example). The name of the function used for the tag can be named whatever you want.

var person = 'Mike'; var age = 28; function myTag(strings, personExp, ageExp) { var str0 = strings[0]; // "that " var str1 = strings[1]; // " is a " // There is technically a string after // the final expression (in our example), // but it is empty (""), so disregard. // var str2 = strings[2]; var ageStr; if (ageExp > 99){ ageStr = 'centenarian'; } else { ageStr = 'youngster'; } return str0 + personExp + str1 + ageStr; } var output = myTag`that ${ person } is a ${ age }`; console.log(output // that Mike is a youngster

标记函数不需要返回字符串,如下例所示。

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' // "YAY!" var t2Closure = template`${0} ${'foo'}!`; t2Closure('Hello', {foo: 'World'} // "Hello World!"

原始字符串

raw标记模板文字的第一个函数参数上的特殊属性允许您在输入时访问原始字符串,而不处理转义序列。

function tag(strings, ...values) { console.log(strings.raw[0] } tag`string text line 1 \n string text line 2`; // logs "string text line 1 \n string text line 2" , // including the two characters '\' and 'n'

此外,该String.raw()方法存在创建原始字符串就像默认的模板函数和字符串连接会创建。

var str = String.raw`Hi\n${2+3}!`; // "Hi\n5!" str.length; // 6 str.split('').join(',' // "H,i,\,n,5,!"

标记模板文字和转义序列

从ES2016开始,标记的模板字面符合以下转义序列的规则:

  • Unicode escapes started by "\u", for example \u00A9

  • Unicode code point escapes indicated by "\u{}", for example \u{2F804}

  • Hexadecimal escapes started by "\x", for example \xA9

  • Octal literal escapes started by "\" and (a) digit(s), for example \251

这意味着像下面这样的标记模板是有问题的,因为根据ECMAScript语法,解析器查找有效的Unicode转义序列,但发现格式错误的语法:

latex`\unicode` // Throws in older ECMAScript versions (ES2016 and earlier) // SyntaxError: malformed Unicode character escape sequence

标记的模板文字应该允许嵌入语言(例如DSLLaTeX),其他转义序列是常见的。ECMAScript提议模板文字修订(阶段4,将被集成到ECMAScript 2018标准中)从标签模板文字中删除ECMAScript转义序列的语法限制。

但是,非法转义序列仍然必须以“熟”的表示来表示。它们将undefined在“熟化”数组中显示为元素:

function latex(str) { return { "cooked": str[0], "raw": str.raw[0] } } latex`\unicode` // { cooked: undefined, raw: "\\unicode" }

请注意,转义序列限制仅从标记的模板文字中删除,而不是从未标记的模板文字中删除:

let bad = `bad escape sequence: \unicode`;

产品规格

SpecificationStatusComment
ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'Template Literals' in that specification.StandardInitial definition. Defined in several section of the specification: Template Literals, Tagged Templates
ECMAScript Latest Draft (ECMA-262)The definition of 'Template Literals' in that specification.Living StandardDefined in several section of the specification: Template Literals, Tagged Templates
Template Literal RevisionStage 4 draftDrops escape sequence restriction from tagged template literals

浏览器兼容性

FeatureChromeEdgeFirefox (Gecko)Internet ExplorerOperaSafari
Basic support41(Yes)34 (34)No support289
Template Literal RevisionNo supportNo support53 (53)No supportNo supportNo support

FeatureAndroidChrome for AndroidFirefox Mobile (Gecko)IE MobileOpera MobileSafari Mobile
Basic supportNo support4134.0 (34)No support289
Template Literal RevisionNo supportNo support53.0 (53)No supportNo supportNo support