二、ES6系列之模板字符串

模板字面量 是允许嵌入表达式的字符串字面量。你可以使用多行字符串和字符串插值功能。它们在 ES2015 规范的先前版本中被称为“模板字符串”。

基础用法

模板字符串使用反引号 ( ) 来代替普通字符串中的用双引号和单引号;模板字符串可以包含特定语法(${expression})的占位符。

1
2
let message = `Hello World`;
console.log(message);

在模版字符串内使用反引号(`)时,需要在它前面加转义符(\)。

1
2
let message = `Hello \` World`;
console.log(message);

多行字符串

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

1
2
let message = "Hello World, \nThis is the second line";
console.log(message);

在模板字符串中,空格、缩进、换行都会被保留,用模板字符串实现:

1
2
3
let message = `Hello World,
This is the second line`;
console.log(message);

嵌套变量

模板字符串支持嵌入变量,只需要将变量名写在 ${} 之中,其实不止变量,任意的 JavaScript 表达式都是可以的:

1
2
3
4
var a = 5;
var b = 10;
console.log("Fifteen is " + (a + b) + " and not " + (2 * a + b) + ".");
// Fifteen is 15 and not 20.

值得一提的是,模板字符串支持嵌套:

1
2
3
4
5
6
7
8
9
10
11
let arr = [{ value: 1 }, { value: 2 }];
var message = `
<ul>
${arr.map((item) => {
return `
<li>${item.value}</li>
`;
})}
</ul>
`;
console.log(message);

输出结果:

1
2
3
4
5
<ul>
<li>1</li>
,
<li>2</li>
</ul>

上面的”,”是因为 map 后生成的数组转字符串导致的,比如一个数组 [1, 2, 3] 就会被转为 1,2,3;所以我们用 jion 处理它:

1
2
3
4
5
6
7
8
9
10
11
12
13
let arr = [{ value: 1 }, { value: 2 }];
var message = `
<ul>
${arr
.map((item) => {
return `
<li>${item.value}</li>
`;
})
.join("")}
</ul>
`;
console.log(message);

输出结果:

1
2
3
4
5
<ul>
<li>1</li>

<li>2</li>
</ul>

带标签的模板字符串

更高级的形式的模板字符串是带标签的模板字符串。标签使您可以用函数解析模板字符串。标签函数的第一个参数包含一个字符串值的数组。其余的参数与表达式相关。最后,你的函数可以返回处理好的的字符串(或者它可以返回完全不同的东西 , 如下个例子所述)。用于该标签的函数的名称可以被命名为任何名字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var person = "Mike";
var age = 28;

function myTag(strings, ...values) {
console.log(strings); // ["that ", " is a ", ""]
console.log(values); // ['Mike', 28]

// 拼接字符串
let result = strings.reduce((prev, next, i) => {
let value = values[i - 1];
return prev + value + next;
});
return result;
}

var output = myTag`that ${person} is a ${age}`;

console.log(output);
// that Mike is a 28

当然标签函数并不一定需要返回一个字符串,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 ,我们可以通过它来访问模板字符串的原始字符串,而不经过特殊字符的替换。

1
2
3
4
5
6
7
function tag(strings) {
console.log(strings.raw);
}

tag`string text line 1 \n string text line 2`;
// 输出(包含两个\):
// ["string text line 1 \\n string text line 2"]

参考文献