模版字符串是字符串的升级版,通过反引号“·”来标识,这个反引号就是键盘上“1”前面的那个按键。模版字符串在angularJS,reactJs,vue等前端框架横行的状态下,只要你会这几种框中的一种,对模版字符串可以说是一看就会。
var boy={ name:"mooshine", height:"175", age:"30", country:"china", province:"hebei", city:"shijiazhuang", area:"zhaoxian" }; var msg=`The boy's name is ${boy.name} the boy's height is${boy.height}`; console.log(msg);
上面的代码就是模板字符串,模板字符串中可以使用“${...}”的形式来出入变量值。可以说十分方便。但是它对于java开发的jsp页面,可以说是一个撞衫。jsp页面中的EL表达式也是使用“${...}”的形式来引用变量的。如果在jsp页面中使用这个模板字符串,那模版字符串中的变来那个不会到前端解析,在后台解析jsp页面的servlet中就会被替换成“”空字符串了。看来这jsp页面中不能使用模版字符串了。不知道W3C组织是不是对java的jsp页面有很大成见,特意使用和EL表达式重复的插值符号呢?
上面的代码输出的结果如下:
模板字符串除了可以插值外,还会保留书写中的空格换行符,原样输出。而且模板字符串的书写上可以自由换行,而不用添加“\”反斜杠转义空格。
模板字符串是通过一个默认的函数对其中的插值进行运算和连接的。并且模板字符串提供了一个标签函数,这个标签函数会在默认函数处理完字符串后,且还没有输出前调用,可以认为是模版字符串的回调函数,或者拦截器。
function mytag(strings,...values){ console.log(strings); console.log(values); } mytag`age is ${boy.age},country is ${boy.country}`;
标签函数第一个参数是一个数组,是字符串的字面量的一个数组,后面的参数是不定参数,一个参数代表一个表达式的计算结果。如果使用了标签函数的模版字符串,那么他的最终值要由标签函数return返回。
function mytag(strings,...values){ console.log(strings); console.log(values); } var str=mytag`age is ${boy.age},country is ${boy.country}`; console.log(str);
打印结果如下:
因为我们使用了标签函数创建的模版字符串,而没有在标签函数中return最终值,所以str是undefined。要想有最终结果,我们要做标签函数中将字符串字面量数组和表达式运算结果拼接起来返回。
function mytag(strings,...values){ console.log(strings); console.log(values); var arr=[], i= 0, len=values.length; for(;i<len;i++){ arr.push(strings[i]); arr.push(values[i]); } return arr.join(""); } var str=mytag`age is ${boy.age},country is ${boy.country}`; console.log(str);
这样再打印str的结果如下:
我们可以看到上面的打印中,strings还有一个raw属性,raw属性也是一个数组,里面的值跟strings数组的值一样,只是raw数组里面的斜杠没有被转义。
创建模板字符串还可以使用String对象新增的raw方法,raw方法创建的模版字符串和通过字面量创建的结果是一样的。
var str=String.raw`age is ${boy.age},country is ${boy.country}`; console.log(str);
这个没什么好说的,String.raw是js中自带的一个标签函数,跟我们上面的标签函数类似。
下面我用ES5的javascript代码模拟实现模版字符串的功能,从中你可以体会ES6提供的模板字符串的原理。
//匹配插值变量 var vreg=/(?:\$\{)([^}]*)(?:})/g; //匹配字符串字面量 var sreg=/\$\{[^}]*}/; function tempstr(str,callback){ //设置标签函数或默认标签函数 var call=callback||tempstrcall; //插值数组 var varr=[]; //字符串字面量数组 var sarr=[]; var temp; //正则匹配插值表达式放入插值数组中 while((tmp=vreg.exec(str))!=null){ varr.push(tmp[1]); } //通过split获取字符串字面量数组 sarr=str.split(sreg); var i= 0, len=varr.length; //通过new Function计算插值表达式 for(;i<len;i++){ var fn=new Function("return "+varr[i]); varr[i]=fn(); } //调用标签函数 return call(sarr,...varr); } //默认标签函数 function tempstrcall(strings,...values){ var arr=[], i= 0, len=values.length; //排列字面量和插值运算结果的顺序。 for(;i<len;i++){ arr.push(strings[i]); arr.push(values[i]); } //连接字面量字符串和插值运算结果并返回 return arr.join(""); } var ss="age is ${boy.age},country is ${boy.country}"; var tss=tempstr(ss); console.log(tss);
上面这段代码的执行结果如下:
效果跟ES6的模版字符串是一样的,但写法上要通过函数调用的方式,ES6是使用标签的方式,在ES5中无法模拟这个。通过看上面我写的ES5代码模拟的模版字符串的原理,相信你对ES6的模版字符串以及能够深度认识了。