Appearance
15. 标签函数与模板字符串
观察下面代码,你觉得会输出什么?
js
function test(x) {
console.log(x)
}
test `hello`
1
2
3
4
5
2
3
4
5
事实是,这里会打印出一个数组 ['hello']
。没错,模板字符串还支持在前面添加一个函数标签,这个函数标签就是一个函数的函数名。
TIP
MDN: 如果一个模板字符串由表达式开头,则该字符串被称为带标签的模板字符串,该表达式通常是一个函数,它会在模板字符串处理后被调用,在输出最终结果前,你都可以通过该函数来对模板字符串进行操作处理。
定义
标签函数:模板字符串在 JS 底层中会被一个默认函数处理,也就是把接收的字符串和参数拼接起来。我们可以自定义该函数,在模板字符串前面添加一个函数标签(函数名),覆盖 JS 默认的函数处理,就能够手动处理模板字符串了。
js
tagFunction `string text ${expression} string text`
1
参数获取
模板字符串中的字符和插入的 ${}
中的参数都可以在 arguments
中获取或者定义形参获取。
示例1:使用 arguments
获取
js
let user = {
name: 'Murphy',
age: 20
}
function greet() {
console.log(arguments[0])
// ["I'm ", ". I'm ", " years old."]
console.log(arguments[1])
// Murphy
console.log(arguments[2])
// 20
}
greet `I'm ${user.name}. I'm ${user.age} years old.`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
示例2:使用标签函数的形参获取
js
let user = {
name: 'Murphy',
age: 20
}
function greet(strs, name, age) {
console.log(strs[0] + name + strs[1] + age + strs[[2]])
// I'm Murphy. I'm 20 years old.
}
greet`I'm ${user.name}. I'm ${user.age} years old.`
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
结合柯里化:标签函数返回标签函数
js
const tagFunc = (...arg1) => (...arg2) => (...arg3) => arg1 + arg2 + arg3
let res = tagFunc `hello` `world` `123`
console.log(res) // helloworld123
1
2
3
4
5
2
3
4
5
解释:tagFunc
接收一个模板字符串参数,仍然返回一个标签函数,就可以继续接收模板字符串参数,所以可以连续接收三个模板字符串。
标签函数的应用场景
问题来了,讲了这么多,标签函数有啥用?
React 的 styled-components 就是利用标签函数给 UI 设置样式的:styled-components
js
const Button = styled.a`
${props => props.primary && css`
background: white;
color: black;
`}
`
1
2
3
4
5
6
2
3
4
5
6