JavaScript ES6+ 新特性:模板字串(Template Literals)
簡介
在傳統的 JavaScript 中,字串只能使用單引號 (') 或雙引號 ("),若要在字串內插入變數或運算結果,往往需要透過繁瑣的串接 (+) 操作。
ES6(ECMAScript 2015)引入的 模板字串(Template Literals)則以反引號 (`) 包裹,支援 字串插值、多行文字,以及 標籤模板(Tagged Templates)等強大功能,讓程式碼更簡潔、可讀性更高。
對於 初學者,模板字串是學習現代 JavaScript 必備的基礎;對 中級開發者,則是撰寫動態 UI、產生 SQL/HTML 片段、或實作國際化(i18n)時不可或缺的工具。本文將從概念說明、實作範例、常見陷阱到最佳實踐,完整介紹模板字串的使用方式。
核心概念
1. 基本語法:使用反引號與 ${} 插值
const name = 'Alice';
const age = 28;
// 以前的寫法
const messageOld = 'Hello, ' + name + '! You are ' + age + ' years old.';
// 使用模板字串
const messageNew = `Hello, ${name}! You are ${age} years old.`;
console.log(messageOld); // Hello, Alice! You are 28 years old.
console.log(messageNew); // Hello, Alice! You are 28 years old.
- 反引號 (`) 包住整段字串。
${expression}內可以放 任意 JavaScript 表達式,會在執行時自動轉為字串。
2. 多行字串(Multi-line Strings)
傳統字串若要跨行,需要使用 \n 或字串連接。模板字串直接保留換行符號,讓原始排版即為最終結果。
const poem = `靜夜思
床前明月光,
疑是地上霜。
舉頭望明月,
低頭思故鄉。`;
console.log(poem);
提示:字串內的縮排會被保留,若不想保留前導空白,可在模板前後使用
.trim()。
3. 表達式與函式呼叫
${} 不只能放變數,還能直接寫運算或呼叫函式,讓字串產生更具彈性。
function formatCurrency(num) {
return `$${num.toFixed(2)}`;
}
const price = 1234.5;
const receipt = `Total: ${formatCurrency(price)} (含稅)`;
console.log(receipt); // Total: $1234.50 (含稅)
4. 標籤模板(Tagged Templates)
標籤模板允許在字串被解析前先「攔截」字串與插值,常用於 自訂語言、安全過濾、或 國際化。
// 標籤函式:簡易的 HTML 轉義
function escapeHTML(strings, ...values) {
const escape = (str) =>
str.replace(/[&<>"']/g, (c) =>
({
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[c])
);
return strings.reduce((result, str, i) => {
const val = values[i] !== undefined ? escape(String(values[i])) : '';
return result + str + val;
}, '');
}
const userInput = '<script>alert("XSS")</script>';
const safeHTML = escapeHTML`<p>使用者說:${userInput}</p>`;
console.log(safeHTML);
// <p>使用者說:<script>alert("XSS")</script></p>
關鍵:標籤函式的第一個參數是 字串陣列(已分割的文字),之後的參數則是對應的插值值。
5. 逃脫反引號與 ${}
若字串本身需要包含反引號或 ${},必須使用 反斜線(\)逃脫。
const raw = `這是一個反引號:\`,以及插值符號 \${notAVariable}`;
console.log(raw);
// 這是一個反引號:`,以及插值符號 ${notAVariable}
常見陷阱與最佳實踐
| 陷阱 | 說明 | 建議的做法 |
|---|---|---|
| 忘記使用反引號 | 用單/雙引號寫 ${} 會被當成普通字串,插值不會被解析。 |
務必使用 ` 包住整段字串。 |
| 不必要的空白與縮排 | 模板字串保留所有換行與空格,會導致輸出多餘的空白。 | 使用 .trim()、.replace(/\s+/g, ' ') 或將縮排寫在行首。 |
| 在插值中執行副作用 | ${func()} 會在字串組合時立即執行,若 func 有副作用會影響程式行為。 |
避免在插值中呼叫會改變狀態的函式,僅使用純函式或預先計算結果。 |
| 大量模板字串的效能 | 產生極大量的模板字串(例如在迴圈內)會產生許多臨時字串物件。 | 若效能成問題,可改用 Array.join 或 模板函式 緩存結果。 |
| 安全性:XSS 攻擊 | 直接把使用者輸入插入 HTML 會產生 XSS 風險。 | 使用 標籤模板 進行 HTML 轉義,或使用前端框架的自動編碼機制。 |
最佳實踐
- 保持插值純粹:將計算或資料取得的工作放在模板外,插值只負責顯示。
- 使用標籤模板做安全過濾:如上例的
escapeHTML,或利用第三方庫(如lodash.escape)。 - 適度使用
.trim():避免因排版而產生不必要的前後空白。 - 統一風格:在團隊中約定「模板字串皆使用反引號,且每行縮排以 2 空格為基準」。
- 避免過度嵌套:過長的模板字串可拆成小片段,使用函式組合,提高可讀性。
實際應用場景
1. 動態 URL 組合
function buildApiUrl(endpoint, params) {
const query = new URLSearchParams(params).toString();
return `https://api.example.com/${endpoint}?${query}`;
}
const url = buildApiUrl('search', { q: '模板字串', page: 2 });
console.log(url);
// https://api.example.com/search?q=%E6%A8%A1%E6%9D%BF%E5%AD%97%E4%B8%B2&page=2
2. 產生 HTML 片段(搭配安全過濾)
function renderUserCard(user) {
return escapeHTML`
<div class="card">
<h2>${user.name}</h2>
<p>年齡:${user.age}</p>
<p>簡介:${user.bio}</p>
</div>
`;
}
3. 多語系訊息(i18n)
const messages = {
en: (name) => `Welcome, ${name}!`,
zh: (name) => `歡迎,${name}!`,
};
function greet(lang, name) {
return messages[lang]?.(name) ?? messages.en(name);
}
console.log(greet('zh', '小明')); // 歡迎,小明!
4. 日誌與除錯
function logError(err, context) {
console.error(`❌ 錯誤於 ${context.module}
訊息: ${err.message}
堆疊: ${err.stack}`);
}
5. 生成 SQL 查詢(注意避免 SQL 注入)
重要提醒:永遠使用參數化查詢(prepared statements)避免注入,此處僅示範模板字串的排版便利性。
function buildSelect(table, columns, where) {
const cols = columns.join(', ');
const conditions = Object.entries(where)
.map(([k, v]) => `${k} = '${v.replace(/'/g, "''")}'`) // 簡易轉義
.join(' AND ');
return `SELECT ${cols}
FROM ${table}
WHERE ${conditions};`;
}
const sql = buildSelect('users', ['id', 'name'], { status: 'active', role: 'admin' });
console.log(sql);
總結
模板字串是 ES6+ 中最直觀、最具表現力的字串處理工具。透過反引號、${} 插值與標籤模板,我們可以:
- 簡化字串拼接,提升程式可讀性。
- 直接書寫多行文字,免除繁瑣的換行符號。
- 在字串生成前進行安全過濾,降低 XSS、SQL 注入等風險。
- 在實務開發(API URL、HTML 產生、國際化、日誌)中提供一致且易維護的寫法。
掌握模板字串的正確使用與常見陷阱,能讓你在 前端、Node.js 或 全端 專案中寫出更乾淨、更安全的程式碼。未來隨著 Tagged Templates 的生態(例如 styled-components、graphql-tag)持續擴展,模板字串將成為 JavaScript 開發者不可或缺的基礎能力。祝你在 Modern JS 的旅程中,玩得開心、寫得順手!