摘自《ES6标准入门》
标签模板其实不是模板,而是函数调用的一种特殊方式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。
但是,如果模板字符串中有变量,就不再是简单的调用了,而是要将模板字符串先处理成多个参数,再调用函数。
var a = 5;
var b = 10;
tag`Hello ${a + b} world ${a * b}`
// 等同于
tag(['Hello ', ' world ', ''], 15, 50)
tag 函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在数组的第一个成员与第二个成员之间、第二个成员与第三个成员之间,以此类推。 `tag 函数的其他参数都是模板字符串各个变量被替换后的值。由于本例中,模板字符串含有两个变量,因此 tag 会接收到 value1 和 value2 两个参数。 tag 函数所有参数的实际值如下。
- 第一个参数:['Hello ', ' world ', '']
- 第二个参数:15
- 第三个参数:50
也就是说,tag 函数实际上以下面的形式调用。 tag(['Hello ', ' world ', ''], 15, 50)
我们可以按照需要编写 tag 函数的代码。下面是 tag 函数的一种写法以及运行结果。
var a = 5;
var b = 10;
function tag(s, v1, v2) {
console.log(s[0])
console.log(s[1])
console.log(s[2])
console.log(v1)
console.log(v2)
return 'OK'
}
tag`Hello ${a + b} world ${a * b}`
// 'Hello'
// ' world '
// ''
// 15
// 50
// 'OK'
下面一个更复杂的例子:
var total = 30;
var msg = passthru`The total is ${total} (${total*1.5} with tax)`;
function passthru(literals) {
var result = ''
var i = 0;
while (i < literals.length) {
result += literals[i++];
if (i < arguments.length) {
result += arguments[i]
}
}
return result
}
msg // "The total is 30 (45 with tax)"
上面这个例子展示了如何将各个参数按照原来的位置拼接回去。 passthru 函数采用 rest 参数的写法如下。
function passthru(literals, ...values) {
var output = '';
for (var index = 0;index < valus.length; index++) {
output += literals[index]
return output
}
}
“标签模板” 的一个重要应用就是过滤就是 HTML 字符串,防止用户输入恶意内容。
var message = SaferHTML`<P>${sender} has sent you message.</p>`
function SaferHTML(templateData) {
var s = templateData[0];
for(var i = 1; i < arguments.length; i++) {
var arg = String(arguments[i]);
// 替换转义字符
s += arg.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
s += templateData[i]
}
return s
}
上面的代码中,sender 变量往往是由用户提供的,经过 SaferHTML 函数处理,里面的特殊字符都会被转义。
var sender = '<script>alert("abc")</script>'
var message = SaferHTML`<p>${sender} has sent you a message.</p>`
message
// <p><script>alert("abc")</script>
// has sent you a message.</p>
标签模板的另一个应用是多国语言转换(国际化处理)。