你真的了解模版字符串么?
我们来简单的铺垫一下模版字符串出现前的样子, 下面列几个场景:
<div id='container'></div>
<script>
var container = document.querySelector('#container')
var count = 2
// 拼接变量
var inner = '这里有' + count + '个炒粉工'
container.innerText = inner
// 换行
var _inner = '这里有<b>' + count + '</b>个炒粉工,' +
'每天只知道吹水~'
container.innerHTML = _inner
// 双单嵌套(我找不到一个很典型的栗子,随便捏了一个)
var $inner = '这里有' + count + '"(two)"个炒粉工'
// 双套双单套单
var $$inner = '这里'there'balabal'
$$$inner = "这里"there"balabal"
</script>
我们知道当字符串变得很长,用上面的拼接写法是很繁琐的,而且在插入一些javascript template
或者html template
的时候,会写的很冗长。而且一步小心就会因为引号的缺失导致整个template
报错。
这个时候,我们就要请出来我们今天要说的主角---es6
增加的模版字符串。
语法
模板字符串(template string)
是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
下面我们用模版字符串改写一下上面的一些场景:
// 拼接变量
var inner = `这里有${count}个炒粉工`
// 换行
var _inner = `
这里有<b>${count}</b>个炒粉工
每天只知道吹水
`
// 因为模版字符串外部为反引号,所以单双嵌套的场景还是比较少,如果在内部的字符串出现了单双嵌套规则还是和原来一致的。
// javascript template(百度埋点是比较常见的一个了)
var doc = document.body,
hmc = document.createElement('script');
hmc.innerHTML = `
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js";
var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s);
})();
`;
doc.appendChild(hmc);
// 嵌套反引号需要转义
var $r = `这里有`${count}`个炒粉工`
// 表达式
`${count} + ${count} = ${count * 2}` // 2 + 2 = 4
// 运行方法(默认会调用toString)
const $function = function(count) { return `这里有${count}个炒粉工` }
`其实, ${$function(count)}` // 其实,这里有2个炒粉工
// 模版字符串中调用模版字符串
var $$r = `你确定这里是${count > 0 ? `${count}个炒粉工` : '水军'}`
你是不是觉得,这是我要讲的? 你是不是觉得这些你都知道? 我为什么要讲这些?那看看下面这道题,说说结果是什么。
function getPersonInfo(a, b, c) {
console.log(a)
console.log(b)
console.log(c)
}
const per = 'John'
const age = 21
getPersonInfo`${per} is ${age} years old`
如果你做的出来,那么你就不用看下面的文章了,如果你做不出来,那么就话三分钟看看下面你不知道的模版字符串的用法吧。
标签模版
模版字符串可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)
。而这个不是你狭义上理解的模版,这里的标签指的是前面的函数,而后面的模版指的是我们的模版字符串。我们通过栗子来分析一下
* 简单用法
alert`123`
// 等同于
alert('123')
- 模版字符串中存在一个或多个变量(也可称为参数)
const fnc = (val1, val2, val3, val4) => { console.log(val1, val2, val3, val4) }
var $a = 2, $b = 3, $c = 4
fnc`这里有${$a}个,${$b}个${$c}个`
// 控制台输出
["这里有", "个,", "个", "个"] 2 3 4
分析:
从结果上我们可以看出,第一个参数会传入除传入变量之外的所有字符串,如果字符串开始即为一个变量,则参数数组第一个位置为空字符串,字符串相当于被变量在变量所在位置进行分割。之后模版字符串内的所有变量依次作为后面的参数被传入。
这里我们知道如果函数后面紧跟模版字符串的话,模版字符串会先将当前模版解析成多个参数之后传入前面的函数内。参数数量和模版字符串内的变量数量有关。
假设我们这里想要实现一个后面模版字符串传入的是什么,函数就打印什么字符串的话,我们来实现一下
// 上面我有说到,字符串是由变量作为分割界限来split成数组的。(也许不太精确,但是比较好理解)那么也就是说,第一个有字符串组成的数组和后面的变量是一一对应的关系(这里一一对应可以理解为一个接一个的感觉,即一个字符串元素后面即跟一个变量,酱紫我们的思路基本上就有了)
function formatTempalte(element) {
// 这里我们要巧用一下arguments参数, 但注意arguments[1]开始才是我们的变量部分
// 当前element即为被变量分割的字符串元素
var $result = ''
var $count = 0
white($count < element.length) {
$result += element[ $count ++]
// 这个地方其实相当于 $result += element[$count]; $count++
if ($count < arguments.length) {
$result += arguments[$count]
}
}
return $result
}
// 其实我不太习惯用while版本的,我这里改写一下for版本的
function formatTempalte(element) {
// 这里我们要巧用一下arguments参数, 但注意arguments[1]开始才是我们的变量部分
// 当前element即为被变量分割的字符串元素
var $result = ''
var $count = 0
for(;$count < element.length;) {
$result += element[$count]
$count ++
if ($count < arguments.length) {
$result += arguments[$count]
}
}
return $result
}
现在你知道上面那个问题会打印出什么了么?
答案: ["", " is ", " years old"] John 21