标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的是函数,紧跟在后面的模板字符串就是它的参数。html
var a = 5; var b = 10; tag `Hello ${a+b} world ${a*b}`; //这个标识名tag,它是一个函数。整个表达式的返回值,就是tag函数处理模板字符串以后的返回值。函数tag会依次接收到多个参数。
tag函数的第一个参数是一个数组,该数组的成员时模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在数组的第一个成员和第二个成员之间,以此类推。tag函数的其余参数都是模板字符串各个变量被替换后的值,因为本例中,模板字符串含有两个变量,所以tag会接收到value1和value2两个参数。
tag函数全部参数的实际值以下:
——第一个参数:['Hello ',' world ','']
——第二个参数:15
——第三个参数:50
也就是说tag函数其实是如下面的形式调用的
tag(['Hello ',' world ',''],15,50);
咱们能够按照须要编写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.05} with tax)`; function passthru(literals){ var result = ""; var i = 0; while (i<literals.length){ result += literals[i++]; literals这个数组包括的是模板字符串中那些没有变量替换的部分,也就是The total is,(,with tax). if(i<arguments.length){ result+=arguments[i]; //arguments这个数组包括的是所有的参数,由于执行到这里的时候,i已经加1,因此result链接的是模板字符串各个变量被替换后的值。也就是这里的30,31.5 } } return result; } msg //"The total is 30 (31.5 with tax)" //上面这个例子展现了如何将各个参数按照原来的位置拼回去 //passthru函数采用rest参数的写法以下 function passthru(literals,...values){ var output =""; for(var index = 0;index<values.length;index++){ output = literals[index]+values[index]; } output+=literals[index]; return output; }
function SaferHTML(templateData){ var s = templateData[0]; var i; for(i = 1;i<arguments.length;i++){ var arg = String(arguments[i]); //sender里面可能有特殊字符,进行转义 s += arg.replace(/&/g,"&") .replace(/</g,"<") .replace(/>/g,">"); s += templateData[i]; } console.log(i);//2,表示这个循环只执行了一次,由于templateData[0]="<p>",arguments这个数组只有${sender}这个元素,后面一长串字符都是templateData[2]; return s; } var sender = '<script>alert("abc")</script>'; var message = SaferHTML`<p>${sender} has sent you a message.</p>`; console.log(message);
var total = 30; var msg = passthru`The total is ${total}${total*1.05} with tax)`; function passthru(literals){ var result = ""; var i = 0; while (i<literals.length){ console.log(arguments[i]); // console.log(literals[i++]); result += literals[i++]; if(i<arguments.length){ result+=arguments[i]; // console.log(arguments[i]); } } return result; } console.log(msg);
var book = { title:"shiji", author:"simaqian" }; var book1 = { title:"sanguo", author:"luo" }; var myBooks = [book,book1]; function hashTemplate(templateData){ var s = ""; var i = 0; while(i<templateData.length){ s += templateData[i++]; if(i<arguments.length){ s += arguments[i]; } } return s; } var libraryHtml = hashTemplate` <ul> #for book in ${myBooks} <li><i>${book.title}</i> by ${book.author}</li> #end </ul> `; console.log(libraryHtml);
在谷歌浏览器中,运行出来,仍是自己,没有变化。函数
ES6还为原生的String对象提供了raw方法
String.raw方法每每用来充当模板字符串的处理函数,返回一个反斜线都被转义(即反斜线前面再加一个反斜线)的字符串,对应于替换变量后的模板字符串
String.rawHi\n${2+3}!
;
//"Hi\n5!"3d
String.rawHi\\n
//"Hi\n"rest
String.raw = function(strings,...values){ var output = ""; for(var index = 0;index<values.length;index++){ output += strings.raw[index]+values[index]; } output += strings.raw[index]; return output; }
String.raw方法能够做为处理模板字符串的基本方法,它会将全部变量替换,并对反斜线进行转义,方便下一步做为字符串使用
String.raw方法也能够做为正常的函数使用,这时,其第一个参数应该是一个具备raw属性的对象,且raw属性的值应该是一个数组。code
String.raw({raw:'test'},0,1,2); //"t0e1s2t" //等同于 String.raw({raw:['t','e','s','t']},0,1,2);