標籤模板其實不是模板,而是函數調用的一種特殊形式。「標籤」指的是函數,緊跟在後面的模板字符串就是它的參數。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);