JavaScript 核心觀念(72) - ES6 章節:Template Literial - 標籤樣板字面值

前言

接下來這一篇將會介紹比較進階的用法,也就是標籤樣板字面值。

標籤樣板字面值

首先「標籤樣板字面值」是樣板字面值的進階用法,首先先看一段範例程式碼:

1
2
const myName = 'Ray';
console.log(`Hello ${myName}!`); // Hello Ray!

上面是一個非常簡易的樣板字面值的基本寫法,那麼標籤樣板字面值是如何撰寫呢?其實寫法很特別是像這樣:

1
2
3
4
5
6
7
const myName = 'Ray';

function fn(strings, arg) {
console.log(`strings:${strings}`, `arg:${arg}`); // strings:Hello ,! arg:Ray
}

fn`Hello ${myName}!`;

宣告變數到宣告函式相信你應該沒有什麼太大問題,但如果你改成以下這樣是會變成另一個結果

1
2
3
4
5
6
7
const myName = 'Ray';

function fn(strings, arg) {
console.log(`strings:${strings}`, `arg:${arg}`); // strings:Hello Ray! arg:undefined
}

fn(`Hello ${myName}!`);

所以這邊正確的寫法是前面第一種的寫法。

那麼為什麼標籤樣板字面值輸出會像這樣 strings:Hello ,! arg:Ray 呢?讓我們看一下 MDN 的說明:

標籤樣板字面值是一種更高級的樣板字面值形式,允許你透過標籤函數操作樣板字面值的輸出。標籤函數的第一個參數是一字串陣列,其餘參數則是處理過的表達式。最終,你可以返回一個經處理後的字串,甚至是完全不一樣的東西(如下述第二個範例中)。

因此當我們使用標籤樣板字面值時,函式的第一個參數就會是字串的陣列,而第二個餐數則是準備傳入的變數,所以才會這樣呈現 strings:Hello ,! arg:Ray

那麼我們有可能所傳入的變數數量是不一定的,因此這邊在第二個參數就可以使用其餘運算子來解決:

1
2
3
4
5
6
7
8
9
const myName = 'Ray';
const Url = 'https://israynotarray.com/';

function fn(strings, ...arg) {
console.log(arg);
console.log(`strings:${strings}`, `arg:${arg[0]} ${arg[1]}`); // strings:Hello ,! arg:Ray
}

fn`Hello ${myName}! My Blog Url is ${Url}`; // strings:Hello ,! My Blog Url is , arg:Ray https://israynotarray.com/

這邊要注意第一個參數永遠只會傳入非變數的字串,所以請不要將它改成其餘參數,因為沒有必要。

標籤樣板字面值有哪些進階用法呢?第一種是大量給予特定 HTML 樣式,例如給予粗體標籤:

1
2
3
4
5
6
7
8
const myName = 'Ray';
const Url = 'https://israynotarray.com/';

function fn(strings, ...arg) {
return strings.map((str, i) => `${str}${arg[i] ? `<strong>${arg[i]}</strong>` : ''}`).join('');
}

fn`Hello ${myName}! My Blog Url is ${Url}`; // 'Hello <strong>Ray</strong>! My Blog Url is <strong>https://israynotarray.com/</strong>'

當然上面還可以更極致的短寫:

1
2
3
4
5
6
const myName = 'Ray';
const Url = 'https://israynotarray.com/';

const fn = (strings, ...arg) => strings.map((str, i) => `${str}${arg[i] ? `<strong>${arg[i]}</strong>` : ''}`).join('');

fn`Hello ${myName}! My Blog Url is ${Url}`; // 'Hello <strong>Ray</strong>! My Blog Url is <strong>https://israynotarray.com/</strong>'

第二種常見的標籤樣板字面值則是預防 XSS 攻擊

1
2
3
4
5
function convertHTML (strings, ...keys) {
return strings.map((str, i) => `${str}${keys[i] ? keys[i].replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'): ''}`).join('');
}

convertHTML`<p>超連結:${Url}</p>`;

透過上面的方法就可以避免 XSS 攻擊,最主要原因是我們將 <>& 替換成 ASCII Code,也就是單純的字串,因此傳入的變數就可以避免 XSS 攻擊問題。

參考文獻