「この文字列結合、読みづらい…」 「HTMLやSQLを文字列で書くのが辛い」
あなたのコードにも、+
演算子による文字列結合がたくさん含まれていませんか?文字列を結合するたび、引用符やプラス記号の位置を確認し、エスケープ文字に気を配る必要があり、可読性の低下やバグの温床となっています。
ES6で導入されたテンプレートリテラルは、こうした問題を解決する強力な機能です。この記事では、実践的なユースケースと、現場でよく遭遇する「困った」の解決策を紹介します。
基本的な書き方と従来記法との違い
テンプレートリテラルは、バッククォート()で囲んだ文字列の中で
${}`を使って変数や式を埋め込むことができます。単純な文字列結合でも、コードの可読性が大きく向上します:
// 従来の文字列結合
const name = "田中";
const age = 25;
const message = name + "さんは" + age + "歳です。";
// テンプレートリテラルを使用
const message = `${name}さんは${age}歳です。`;
実践的なユースケースと解決策

HTML構築パターン
HTMLの構築は、テンプレートリテラルが最も真価を発揮する場面の1つです。従来の文字列結合と比べて、コードの構造が視覚的に理解しやすくなり、メンテナンス性も向上します:
// 従来の書き方
function createUserCard(user) {
return '<div class="user-card">' +
'<h2>' + user.name + '</h2>' +
'<p class="' + (user.isAdmin ? 'admin' : 'normal') + '">' +
user.role +
'</p>' +
'</div>';
}
// テンプレートリテラルを使用
function createUserCard(user) {
return `
<div class="user-card">
<h2>${user.name}</h2>
<p class="${user.isAdmin ? 'admin' : 'normal'}">
${user.role}
</p>
</div>
`;
}
インデントの制御
HTMLを構築する際、インデントの扱いに注意が必要です:
// BAD: 余分なインデントが含まれる
function createList(items) {
return `
<ul>
${items.map(item => `
<li>${item}</li>
`).join('')}
</ul>
`;
}
// GOOD: インデントを制御
function createList(items) {
return `
<ul>
${items.map(item => `<li>${item}</li>`).join('\n ')}
</ul>`;
}
条件分岐を含む文字列生成
複雑な条件分岐が必要な場合は、テンプレートリテラル内で直接三項演算子を使用するか、関数に切り出すことで可読性を保てます:
// BAD: テンプレートリテラル内で複雑な条件分岐
const message = `
${user.name}さんは
${user.age >= 20
? user.hasDrivingLicense
? '運転可能です'
: '免許を取得できます'
: '運転できません'
}
`;
// GOOD: 関数で条件分岐を分離
const getDrivingStatus = user => {
if (user.age < 20) return '運転できません';
if (user.hasDrivingLicense) return '運転可能です';
return '免許を取得できます';
};
const message = `${user.name}さんは${getDrivingStatus(user)}`;
SQLクエリの構築
動的なSQLクエリの構築では、パラメータのエスケープに特に注意を払いながら、見やすいクエリを作成できます:
// BAD: SQLインジェクションの危険性
const query = `
SELECT * FROM users
WHERE name = '${userName}'
AND age > ${age}
`;
// GOOD: パラメータ化された方法
const createQuery = (conditions) => {
const whereClauses = [];
const params = [];
if (conditions.name) {
whereClauses.push('name = ?');
params.push(conditions.name);
}
if (conditions.minAge) {
whereClauses.push('age > ?');
params.push(conditions.minAge);
}
const whereClause = whereClauses.length
? `WHERE ${whereClauses.join(' AND ')}`
: '';
return {
query: `
SELECT * FROM users
${whereClause}
ORDER BY created_at DESC
`,
params
};
};
よくある落とし穴と対処法
パフォーマンスの注意点
大量の文字列結合が必要な場合、テンプレートリテラルの使用は必ずしもベストな選択とは限りません:
// BAD: 大量のループでの使用
let html = '';
for (const item of items) {
html += `<li>${item.name}: ${item.price}円</li>`;
}
// GOOD: 配列のメソッドを活用
const html = items
.map(item => `<li>${item.name}: ${item.price}円</li>`)
.join('');
エスケープ処理の必要性
テンプレートリテラルでHTML or SQLを構築する際は、XSSやSQLインジェクションを防ぐため、適切なエスケープ処理が重要です:
// BAD: ユーザー入力を直接使用
const userInput = '<script>alert("危険")</script>';
const html = `<div>${userInput}</div>`;
// GOOD: エスケープ処理を行う
const escapeHtml = (str) => {
return str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
const html = `<div>${escapeHtml(userInput)}</div>`;
文字列の整形テクニック
長い文字列や複雑なフォーマットが必要な場合は、適切な改行とインデントを使用することで可読性を保てます:
// BAD: 1行が長すぎる
const productInfo = `商品名: ${product.name}, 価格: ${product.price}円, 在庫: ${product.stock}個, カテゴリ: ${product.category}, 登録日: ${product.createdAt}`;
// GOOD: 適切な改行と整形
const productInfo = `
商品情報
------------------------
商品名: ${product.name}
価格: ${product.price}円
在庫: ${product.stock}個
カテゴリ: ${product.category}
登録日: ${product.createdAt}
`;
実務でのベストプラクティス

レビュー時のチェックポイント
コードレビューでは、以下の点に特に注意を払いましょう:
- 可読性
- 式が複雑すぎないか
- 適切な改行とインデントが使われているか
- 長い式は関数に分離されているか
- セキュリティ
- ユーザー入力が適切にエスケープされているか
- SQLインジェクションの危険はないか
- パフォーマンス
- 大量の繰り返しで非効率な結合が行われていないか
- 不要な文字列生成が発生していないか
コーディングガイドライン
- 複雑な条件は関数に分離する
- HTMLやSQLの構築では適切なインデントを維持する
- 大量の文字列結合には配列の
join
メソッドを使用する - ユーザー入力を含む場合は必ずエスケープ処理を行う
- 長い文字列は適切な箇所で改行する
テンプレートリテラルは、適切に使用することで可読性の高いコードを実現できます。特にHTMLやSQLの構築では、従来の文字列結合と比べて圧倒的に扱いやすくなります。一方で、パフォーマンスやセキュリティには十分な注意が必要です。本記事で紹介したパターンを参考に、プロジェクトに適した使い方を見つけてください。