【JavaScript】改行をエスケープせずに文字列として扱う方法|テンプレートリテラル・配列join・String.rawの使い分け

【JavaScript】改行をエスケープせずに文字列として扱う方法|テンプレートリテラル・配列join・String.rawの使い分け JavaScript

JavaScriptで文字列に改行を含める方法といえば\nが定番ですが、テンプレートリテラル(バッククォート)を使えばエスケープなしで改行をそのまま書けます。

この記事では、テンプレートリテラルの基本から、配列 + joinString.raw改行を含む正規表現まで、エスケープせずに改行を扱う方法を網羅的に解説します。

この記事で学べること

  • テンプレートリテラルで改行をそのまま含める基本構文
  • 式の埋め込み${})と複数行文字列の組み合わせ
  • 配列 + joinで改行を挿入する方法
  • String.rawでエスケープシーケンスを無効化する方法
  • HTMLテンプレート生成の実務パターン
  • \n vs テンプレートリテラルの比較と使い分け
  • 改行を含む文字列の注意点とインデント対策
スポンサーリンク

テンプレートリテラルで改行を含める(基本)

ES2015(ES6)で導入されたテンプレートリテラルは、バッククォート(`)で囲む文字列です。ソースコード上の改行がそのまま文字列に含まれます。

テンプレートリテラルで改行
const message = `1行目
2行目
3行目`;

console.log(message);

実行結果

1行目
2行目
3行目

ダブルクォートやシングルクォートで同じことを書くと、\nを使う必要があります。

従来の方法(\nが必要)
// \n を使ったエスケープが必要
const message = "1行目\n2行目\n3行目";

// 文字列連結で改行を入れる方法もあるが冗長
const message2 = "1行目\n" +
                  "2行目\n" +
                  "3行目";

ポイント:テンプレートリテラルを使えば\n+による連結が不要になり、コードの可読性が大幅に向上します。

式の埋め込み(${})と複数行文字列

テンプレートリテラルの最大の特徴は、改行式の埋め込みを同時に使えることです。

変数・式の埋め込み
const name = "田中";
const age = 30;

const profile = `名前: ${name}
年齢: ${age}歳
来年: ${age + 1}歳`;

console.log(profile);

実行結果

名前: 田中
年齢: 30歳
来年: 31歳

${}の中には変数だけでなく、関数呼び出し三項演算子などの式も書けます。

式・関数の埋め込み
const items = ["りんご", "みかん", "バナナ"];

const report = `商品数: ${items.length}個
一覧: ${items.join(", ")}
先頭: ${items[0].toUpperCase()}`;

console.log(report);

実行結果

商品数: 3個
一覧: りんご, みかん, バナナ
先頭: りんご

HTMLテンプレートの生成(実務パターン)

テンプレートリテラルが最も活躍するのがHTML文字列の生成です。改行とインデントをそのまま書けるため、HTMLの構造が一目で分かります。

HTMLテンプレートの生成
function createCard(user) {
  return `<div class="card">
  <h2>${user.name}</h2>
  <p>${user.email}</p>
  <span class="role">${user.role}</span>
</div>`;
}

const html = createCard({
  name: "田中太郎",
  email: "tanaka@example.com",
  role: "管理者"
});

console.log(html);

実行結果

<div class="card">
  <h2>田中太郎</h2>
  <p>tanaka@example.com</p>
  <span class="role">管理者</span>
</div>

配列をループしてリストを生成

mapとjoinでリスト生成
const fruits = ["りんご", "みかん", "バナナ"];

const list = `<ul>
${fruits.map(f => `  <li>${f}</li>`).join("\n")}
</ul>`;

console.log(list);

実行結果

<ul>
  <li>りんご</li>
  <li>みかん</li>
  <li>バナナ</li>
</ul>

配列 + join で改行を挿入する

テンプレートリテラルとは別のアプローチとして、配列の各要素を改行文字で結合する方法があります。

配列 + join
const lines = [
  "1行目: ヘッダー",
  "2行目: 本文",
  "3行目: フッター"
];

const text = lines.join("\n");
console.log(text);

実行結果

1行目: ヘッダー
2行目: 本文
3行目: フッター

この方法は動的に行を追加・削除したい場合に便利です。

条件に応じて行を追加
const isAdmin = true;

const lines = [
  "ユーザー: 田中太郎",
  "メール: tanaka@example.com",
];

// 条件に応じて行を追加
if (isAdmin) {
  lines.push("権限: 管理者");
}

console.log(lines.join("\n"));

実行結果

ユーザー: 田中太郎
メール: tanaka@example.com
権限: 管理者

String.raw でエスケープを無効化する

String.rawはタグ付きテンプレートリテラルの一種で、\n\tなどのエスケープシーケンスをそのままの文字列として扱います。

String.raw の動作
// 通常のテンプレートリテラル → \n が改行になる
const normal = `Line1\nLine2`;
console.log(normal);
// Line1
// Line2

// String.raw → \n がそのまま文字列になる
const raw = String.raw`Line1\nLine2`;
console.log(raw);
// Line1\nLine2

String.raw の活用場面

ファイルパスや正規表現を書きやすくする
// Windowsのファイルパス(\をエスケープ不要)
const path = String.raw`C:\Users\tanaka\Documents`;
console.log(path);
// C:\Users\tanaka\Documents

// 正規表現パターンの記述
const pattern = String.raw`\d{3}-\d{4}`;
const regex = new RegExp(pattern);
console.log(regex.test("123-4567"));
// true

注意:String.rawはエスケープシーケンスを無効化しますが、${}による式の埋め込みは通常通り動作します。

改行を含める方法の比較

方法 構文 特徴 適した場面
\n エスケープ "行1\n行2" ES5以前でも使える 短い文字列、レガシー環境
テンプレートリテラル `行1(改行)行2` 改行・式埋め込みが自然 HTML生成、複数行テキスト
配列 + join ["行1","行2"].join("\n") 動的に行を操作可能 条件付きの行追加・削除
String.raw String.raw`\n` エスケープを無効化 パス、正規表現パターン

注意点:インデントが文字列に含まれる

テンプレートリテラルはソースコードの改行・空白がそのまま文字列に入ります。関数内で使うと不要なインデントが含まれることがあります。

インデントが含まれる問題
function getMessage() {
  return `1行目
  2行目
  3行目`;  // ← 2行目・3行目の先頭にスペースが入る
}

console.log(getMessage());

実行結果

1行目
  2行目
  3行目

対策1: 行頭を揃える

行頭を左端に揃える
function getMessage() {
  return `1行目
2行目
3行目`;  // ← 見た目は崩れるが出力は正しい
}

対策2: 共通インデントを除去するヘルパー関数

dedent関数で共通インデントを除去
function dedent(str) {
  const lines = str.split("\n");
  const nonEmpty = lines.filter(l => l.trim());
  const minIndent = Math.min(
    ...nonEmpty.map(l => l.match(/^\s*/)[0].length)
  );
  return lines.map(l => l.slice(minIndent)).join("\n").trim();
}

const html = dedent(`
  <div>
    <p>Hello</p>
  </div>
`);

console.log(html);

実行結果

<div>
  <p>Hello</p>
</div>

ポイント:npmパッケージのdedentを使えば、同様の処理をより手軽に実現できます。

タグ付きテンプレートリテラル

テンプレートリテラルの前に関数名を付けると、文字列の処理をカスタマイズできます。これをタグ付きテンプレートリテラルと呼びます。

タグ付きテンプレートリテラルの例
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const value = values[i] !== undefined
      ? `<strong>${values[i]}</strong>`
      : "";
    return result + str + value;
  }, "");
}

const name = "田中";
const role = "管理者";

const msg = highlight`${name}さんは
${role}です`;

console.log(msg);

実行結果

<strong>田中</strong>さんは
<strong>管理者</strong>です

タグ付きテンプレートの活用例

  • String.raw: エスケープ無効化(前述)
  • HTMLエスケープ: XSS対策として埋め込み値をサニタイズ
  • 国際化(i18n): 翻訳キーの解決
  • CSS-in-JS: styled-componentsなどで使用

ブラウザ対応状況

ブラウザ / 環境 テンプレートリテラル String.raw
Chrome 41+ 41+
Firefox 34+ 34+
Safari 9+ 9+
Edge 12+ 12+
Node.js 4+ 4+
IE 11 非対応 非対応

ポイント:IE11を除くすべてのモダンブラウザで対応しています。IE11対応が必要な場合はBabelなどのトランスパイラを使用してください。

よくある質問(FAQ)

Q. JavaScriptで複数行文字列を1行にまとめるには?
A. replace(/\n/g, ” “)で改行をスペースに置換するか、split(“\n”).join(” “)で分割後結合します。複数の連続スペースはreplace(/\s+/g, ” “)で1つにまとめられます。
Q. テンプレートリテラルの余分なインデントを取り除くには?
A. 各行を分割してtrim()し、再度join(“\n”)します。またはdedentライブラリを使う方法もあります。ES2025で提案中のString.dedent()が将来的に標準化される予定です。
Q. 改行の種類(\r\n、\n、\r)を統一するには?
A. replace(/\r\n|\r/g, “\n”)でWindowsとMacの改行コードをUnix形式に統一できます。逆にWindows形式にするにはreplace(/\n/g, “\r\n”)を使います。

まとめ

用途 推奨方法 理由
複数行テキスト・HTML生成 テンプレートリテラル 改行と式埋め込みが自然
動的な行の追加・削除 配列 + join 条件に応じた行操作が容易
パス・正規表現パターン String.raw \をエスケープ不要
レガシー環境(IE11) \n エスケープ ES5互換

改行を含む文字列を扱う場面では、まずテンプレートリテラルを検討しましょう。\nのエスケープが不要になり、コードの可読性と保守性が向上します。

関連記事