- JavaScript
JavaScript replaceとreplaceAllの違い|全置換のやり方
replace は「最初に見つかった1か所」を置換し、replaceAll は「見つかったすべて」を置換するメソッドです。 ただし replace でも、正規表現に g フラグを付ければ全置換になります。文字列をそのまま全置換したいなら replaceAll、パターンで置換したいなら g フラグつきの正規表現、と覚えると迷いません。
この記事では、replace と replaceAll に文字列と正規表現を渡す4通りを同じ入力で実行して比べた結果表を最初に示します。そのうえで、g フラグなしの正規表現を replaceAll に渡したときの TypeError、置換文字列の中で使える特殊パターンの一覧、コールバック関数の引数、「.」や「?」を含む文字列のエスケープ(RegExp.escape の対応状況と代替関数)、複数語の一括置換などのコピペ集、split と join を使う方法との比較まで、Node.js 22.22.2 の実行結果つきで解説します。
replace と replaceAll の違い早見表
入力は const s = "a.b.c A.B" で、「.」を「-」に置き換えます。
| 書き方 | 実行結果 | 置換される範囲 |
|---|---|---|
s.replace(".", "-")(文字列) |
"a-b.c A.B" |
最初の1か所だけ |
s.replace(/\./, "-")(正規表現・g なし) |
"a-b.c A.B" |
最初の1か所だけ |
s.replace(/\./g, "-")(正規表現・g あり) |
"a-b-c A-B" |
すべて |
s.replaceAll(".", "-")(文字列) |
"a-b-c A-B" |
すべて |
s.replaceAll(/\./g, "-")(正規表現・g あり) |
"a-b-c A-B" |
すべて |
s.replaceAll(/\./, "-")(正規表現・g なし) |
TypeError | ― |
s.replace(/./g, "-")(エスケープなし) |
"---------" |
すべての文字(「.」が任意の1文字の意味になる) |
s.split(".").join("-") |
"a-b-c A-B" |
すべて |
使い分けの目安は次のとおりです。
| やりたいこと | おすすめ |
|---|---|
| 決まった文字列をすべて置換する | replaceAll("探す文字", "置換後") |
| 最初の1か所だけ置換する | replace("探す文字", "置換後") |
| パターン(数字の並び、空白の連続など)で置換する | replace(/パターン/g, "置換後") |
| 大文字と小文字を区別せずに置換する | replace(/パターン/gi, "置換後") |
| 変数に入った文字列をすべて置換する | replaceAll(変数, "置換後")(エスケープ不要) |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「JavaScript replaceとreplaceAllの違い|全置換のやり方」
検証環境と4通りの実行結果
| 項目 | 値 |
|---|---|
| Node.js | 22.22.2 |
| ブラウザ | Chromium 141(TypeError のメッセージと RegExp.escape の有無・動作を確認) |
| TypeScript | 7.0.2(tsc --noEmit で target ごとのエラーを確認) |
そのほかのブラウザ、Node.js のほかのバージョンでは実行していません(未実行)。
同じ入力で4通りを比べる
const s = "a.b.c A.B";
console.log(s.replace(".", "-")); // 1. replace + 文字列
console.log(s.replace(/\./g, "-")); // 2. replace + 正規表現(g)
console.log(s.replaceAll(".", "-")); // 3. replaceAll + 文字列
console.log(s.replaceAll(/\./g, "-")); // 4. replaceAll + 正規表現(g)
実行結果:
a-b.c A.B
a-b-c A-B
a-b-c A-B
a-b-c A-B
1だけが最初の1か所で止まり、2〜4はすべて置換されました。2と4は同じ結果なので、正規表現を使うなら replace と replaceAll のどちらを選んでもかまいません。replaceAll と書いておくと「全置換のつもりである」ことがコードを読む人に伝わりやすく、g の付け忘れもエラーで知らせてくれます。
元の文字列は変わらない
replace も replaceAll も、新しい文字列を返します。元の文字列は書き換わりません。
let t = "aaa";
t.replaceAll("a", "b"); // 戻り値を受け取っていない
console.log(t);
aaa
結果を使うには、t = t.replaceAll("a", "b"); のように変数へ入れ直します。
g フラグなしの正規表現を replaceAll に渡すと TypeError
replaceAll に正規表現を渡すときは、g フラグが必須です。付けないとエラーになります。
"a.b.c".replaceAll(/\./, "-");
"abc".replaceAll(new RegExp("a", "i"), "-");
実行結果(Node.js 22.22.2 と Chromium 141 で同じメッセージ):
TypeError: String.prototype.replaceAll called with a non-global RegExp argument
MDN の replaceAll のページでは「TypeError: replaceAll must be called with a global RegExp」という文面が紹介されています。エンジンによってメッセージの文面が違うので、どちらを見かけても同じ原因(g フラグがない)だと判断できます。
直す前と後
// 直す前:g がないので TypeError
text.replaceAll(/\s+/, " ");
// 直した後:g を付ける
text.replaceAll(/\s+/g, " ");
// new RegExp で作るときは、第2引数に "g" を含める
text.replaceAll(new RegExp(word, "gi"), "");
「全置換のつもりなのに1か所しか置換されなかった」という静かなずれを防ぐための仕組みなので、エラーが出たら g を足せば解決します。
そのほかのエラーと原因
| コード | 実行結果 | 原因 |
|---|---|---|
null.replace("a", "b") |
TypeError: Cannot read properties of null (reading 'replace') | 対象が null |
(123).replace("1", "2") |
TypeError: 123.replace is not a function | 対象が数値。String(123) で文字列にする |
new RegExp("?", "g") |
SyntaxError: Invalid regular expression: /?/g: Nothing to repeat | 「?」をエスケープせずに正規表現にした |
new RegExp("(", "g") |
SyntaxError: Invalid regular expression: /(/g: Unterminated group | 「(」をエスケープせずに正規表現にした |
下の2つは、あとの「記号を含む文字列を全置換する」で対処法を紹介します。
置換文字列の中で使える特殊パターン
置換後の文字列(第2引数)の中では、「$」で始まる特別な書き方が使えます。一致した部分を再利用できる便利な仕組みです。
特殊パターン一覧
| 書き方 | 意味 | コード | 実行結果 |
|---|---|---|---|
$& |
一致した部分そのもの | "cat".replace(/a/, "[$&]") |
"c[a]t" |
$1、$2 … |
丸かっこで囲んだ n 番目のグループ | 下の日付の例 | "03/10/2026" |
$<name> |
名前つきグループ | 下の日付の例 | "2026年10月03日" |
$$ |
「$」という文字そのもの | "price: 100".replace("100", "$$100") |
"price: $100" |
$ とバッククォート |
一致した部分より前の文字列 | 下のコード | "a[a]c" |
$' |
一致した部分より後ろの文字列 | "abc".replace("b", "[$']") |
"a[c]c" |
const d = "2026-10-03";
// $1 $2 $3:番号で参照
console.log(d.replace(/(\d+)-(\d+)-(\d+)/, "$3/$2/$1"));
// $<name>:名前で参照
console.log(d.replace(/(?<y>\d+)-(?<m>\d+)-(?<d>\d+)/, "$<y>年$<m>月$<d>日"));
// $ とバッククォート:一致より前の部分
console.log("abc".replace("b", "[$`]"));
実行結果:
03/10/2026
2026年10月03日
a[a]c
これらのパターンは、探す側が文字列のときも有効です。
console.log("a+b".replaceAll("+", " [$&] "));
a [+] b
置換後の文字列に「$」が入るときの注意
特殊パターンは便利な一方で、置換後の文字列に利用者が入力した値や金額の表記を入れるときに、意図と違う結果になることがあります。
console.log("料金は X です".replace("X", "$&100")); // $& が「X」に展開される
console.log("cost".replace("cost", "$$")); // $$ が「$」1文字になる
料金は X100 です
$
「$&100」という文字をそのまま入れたかったのに、$& が一致した部分(X)に置き換わりました。置換後の文字列を関数で返すと、特殊パターンは解釈されません。
console.log("料金は X です".replace("X", () => "$&100"));
料金は $&100 です
変数に入った値をそのまま差し込みたいときは、str.replaceAll(from, () => to) の形にしておくと安心です。
なお、グループのない置換で $1 と書いた場合は、そのまま文字として残りました。
console.log("abc".replace("b", "$1")); // "a$1c"
コールバック関数で置換する
第2引数に関数を渡すと、一致するたびにその関数が呼ばれ、戻り値が置換後の文字列になります。計算や条件分岐を入れたいときに使います。
関数に渡される引数
| 順番 | 引数 | 内容 |
|---|---|---|
| 1 | match | 一致した部分 |
| 2〜 | p1, p2, … | 丸かっこのグループ(ある数だけ) |
| その次 | offset | 一致した位置(0始まり) |
| その次 | string | 元の文字列全体 |
| 最後 | groups | 名前つきグループのオブジェクト(名前つきグループがあるときだけ) |
実際に全部の引数を表示してみます。
"2026-10-03".replace(/(?<y>\d+)-(\d+)/, (...args) => {
console.log(args);
return "";
});
"abc".replace("b", (...args) => {
console.log(args);
return "";
});
実行結果:
[
'2026-10',
'2026',
'10',
0,
'2026-10-03',
[Object: null prototype] { y: '2026' }
]
[ 'b', 1, 'abc' ]
1つ目は「一致した部分、グループ2つ、位置、元の文字列、名前つきグループ」の順です。2つ目のように探す側が文字列のときは、グループがないので「一致した部分、位置、元の文字列」の3つになります。
コールバックの使用例
// 各単語の先頭を大文字にする
console.log("hello world".replace(/\b\w/g, (c) => c.toUpperCase()));
// 数字だけ 1.1 倍する
console.log("pen 100 note 250".replace(/\d+/g, (n) => Math.round(n * 1.1)));
// 一致した位置を使う
console.log("a-a-a".replace(/a/g, (m, i) => i));
// {name} の形のひな形に値を差し込む
const data = { name: "佐藤", item: "備品" };
console.log(
"こんにちは、{name}さん。{item}の件です。".replace(/\{(\w+)\}/g, (_, key) => data[key] ?? "")
);
実行結果:
Hello World
pen 110 note 275
0-2-4
こんにちは、佐藤さん。備品の件です。
記号を含む文字列を全置換する(エスケープと RegExp.escape)
「.」「?」「(」「+」などの記号は、正規表現の中では特別な意味を持ちます。記号を含む文字列を全置換するときは、replaceAll に文字列のまま渡すのがいちばん簡単です。
正規表現にすると意図と違う結果になる例
const v = "v1.0 v1x0 v1.0";
console.log(v.replace(new RegExp("1.0", "g"), "2.0")); // エスケープなし
console.log(v.replaceAll("1.0", "2.0")); // 文字列のまま
実行結果:
v2.0 v2.0 v2.0
v2.0 v1x0 v2.0
1つ目は、正規表現の「.」が「任意の1文字」を意味するため、「1x0」まで置換されました。2つ目の replaceAll は、文字列を文字どおりに探すので「1.0」だけが置換されています。
方法の比較
| 方法 | コード | 向いている場面 |
|---|---|---|
| replaceAll に文字列で渡す | str.replaceAll(word, to) |
大文字小文字を区別する単純な全置換 |
| 自作のエスケープ関数 + new RegExp | new RegExp(escapeRegExp(word), "gi") |
i フラグなど正規表現の機能と組み合わせたい |
| RegExp.escape + new RegExp | new RegExp(RegExp.escape(word), "gi") |
RegExp.escape が使える実行環境 |
代替のエスケープ関数(どの環境でも使える)
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
console.log(escapeRegExp("1.5?(a)"));
// 「1.0」だけを全置換
console.log("v1.0 v1x0 v1.0".replace(new RegExp(escapeRegExp("1.0"), "g"), "2.0"));
// 記号を含む語を、大文字小文字を区別せずに全置換
console.log("What? what? WHAT?".replace(new RegExp(escapeRegExp("what?"), "gi"), "OK"));
実行結果:
1\.5\?\(a\)
v2.0 v1x0 v2.0
OK OK OK
この関数自体が、先ほどの特殊パターン $&(一致した部分)を使って「記号の前にバックスラッシュを足す」処理をしています。
RegExp.escape の対応状況
RegExp.escape は、文字列を正規表現用にエスケープする組み込みの関数です。MDN の RegExp.escape のページ(今回確認)では Baseline 2025(2025年5月から新しく利用可能) とされています。手元の環境で確かめた結果は次のとおりです。
| 環境 | typeof RegExp.escape | 備考 |
|---|---|---|
| Node.js 22.22.2 | undefined |
未搭載。 代替関数を使う |
| Chromium 141 | function |
動作を確認 |
| TypeScript 7.0.2 | target が es2021 では型エラー、esnext では通る | エラー文は下記 |
| そのほかのブラウザ・Node.js 24 以降 | 未実行 | ― |
Chromium 141 での実行結果です。
RegExp.escape("1.5?(a) b");
"v1.0 v1x0".replace(new RegExp(RegExp.escape("1.0"), "g"), "2.0");
\x31\.5\?\(a\)\x20b
v2.0 v1x0
先頭の「1」が \x31、空白が \x20 という形になっています。自作の関数とは出力の見た目が違いますが、正規表現として使ったときの意味は同じで、「1.0」だけが置換されました。
TypeScript では、target(または lib)の設定によって次のエラーになります。
k2.ts(1,25): error TS2550: Property 'replaceAll' does not exist on type '"a.b"'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2021' or later.
k2.ts(2,18): error TS2550: Property 'escape' does not exist on type 'RegExpConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2025' or later.
1行目は target を es2020 にしたとき、2行目は es2021 のときにも出たエラーです。replaceAll は es2021 以降、RegExp.escape は es2025 以降の lib で型が使えることがわかります。
サーバー側の Node.js が 22 系の場合は、当面は代替関数を用意し、次のように切り替える書き方ができます(Node.js 22.22.2 では代替関数側が使われることを確認)。
const escapeRegExp =
typeof RegExp.escape === "function"
? RegExp.escape
: (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
やりたいこと別コピペ集
逆引き早見表
| やりたいこと | コード | 実行結果 |
|---|---|---|
| 空白の連続を1つにまとめる | "a b \t c".replace(/\s+/g, " ") |
"a b c" |
| 空白をすべて取り除く | " a b ".replaceAll(" ", "") |
"ab" |
| カンマを取り除く | "1,234,567".replaceAll(",", "") |
"1234567" |
| 3桁ごとにカンマを入れる | String(1234567).replace(/\B(?=(\d{3})+(?!\d))/g, ",") |
"1,234,567" |
| 最初の1つだけ置換 | "a-b-c".replace("-", "/") |
"a/b-c" |
| 最後の1つだけ置換 | "a-b-c".replace(/-(?!.*-)/, "/") |
"a-b/c" |
| 大文字小文字を区別せず全置換 | "JavaScript javascript JAVASCRIPT".replace(/javascript/gi, "JS") |
"JS JS JS" |
| スネークケース → キャメルケース | "user_name_kana".replace(/_([a-z])/g, (_, c) => c.toUpperCase()) |
"userNameKana" |
| キャメルケース → スネークケース | "userNameKana".replace(/[A-Z]/g, (c) => "_" + c.toLowerCase()) |
"user_name_kana" |
| 全角スペースを半角に | "a b c".replaceAll(" ", " ") |
"a b c" |
複数の語を一括で置換する
対応表(オブジェクト)を用意し、1回の replace でまとめて置換します。
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const map = { apple: "りんご", banana: "バナナ", pineapple: "パイン" };
const re = new RegExp(
Object.keys(map)
.sort((a, b) => b.length - a.length) // 長い語を先に
.map(escapeRegExp)
.join("|"),
"g"
);
console.log(re);
console.log("apple banana pineapple".replace(re, (m) => map[m]));
実行結果:
/pineapple|banana|apple/g
りんご バナナ パイン
長い語を先に並べるのがポイントです。apple が先にあると、pineapple の中の apple が先に置換されてしまいます。
replaceAll をつなげる方法でも、語が重ならないなら同じ結果になります。
console.log("apple banana".replaceAll("apple", "りんご").replaceAll("banana", "バナナ"));
// りんご バナナ
ただし、入れ替え(a を b に、b を a に)はつなげる方法では書けません。1回目の結果を2回目がもう一度置換するためです。
console.log("a b".replaceAll("a", "b").replaceAll("b", "a")); // つなげる方法
console.log("a b".replace(/a|b/g, (m) => ({ a: "b", b: "a" })[m])); // 1回で置換
a a
b a
n 番目だけ置換する
let count = 0;
console.log("a-b-c-d".replace(/-/g, (m) => (++count === 2 ? "/" : m)));
a-b/c-d
改行を置換する・取り除く
改行は、環境によって \n、\r\n、\r の3種類があります。3つをまとめて扱うパターンが便利です。
// 改行を br タグに
console.log("1行目\n2行目\r\n3行目".replace(/\r\n|\r|\n/g, "<br>"));
// 改行を取り除く
console.log("a\nb\r\nc".replace(/\r?\n/g, ""));
// \n だけなら replaceAll でも書ける
console.log("a\nb\nc".replaceAll("\n", " "));
実行結果:
1行目<br>2行目<br>3行目
abc
a b c
/\r\n|\r|\n/g では、\r\n を先に書くことで、Windows 形式の改行が2つ分として数えられるのを防いでいます。
全角と半角を変換する
// 全角英数字・記号 → 半角
console.log(
"ABC123 a!".replace(/[!-~]/g, (c) => String.fromCharCode(c.charCodeAt(0) - 0xfee0))
);
// 半角英数字・記号 → 全角
console.log(
"ABC123".replace(/[!-~]/g, (c) => String.fromCharCode(c.charCodeAt(0) + 0xfee0))
);
// normalize でまとめて変換(半角カナも全角になる)
console.log("ABC123 ガ".normalize("NFKC"));
実行結果:
ABC123 a!
ABC123
ABC123 ガ
全角の「!」から「~」までの文字は、半角の「!」から「~」までと文字コードが 0xFEE0 だけ離れて並んでいるので、その差を引く(足す)ことで変換できます。英数字と記号とカナをまとめて整えたいなら、3つ目の normalize("NFKC") が短く書けます。全角スペースも半角になりました。
HTML の特殊文字をエスケープする
const escapeHtml = (s) =>
s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
console.log(escapeHtml('<a href="x">T&C</a>'));
<a href="x">T&C</a>
1回の replace で5種類の文字をまとめて置換しているので、「& を置換したあとの結果をもう一度置換してしまう」心配がありません。
絵文字や空文字を置換するとき
console.log("😀a😀".replaceAll("😀", "-")); // 絵文字
console.log("abc".replace("", "-")); // 空文字を探す(replace)
console.log("abc".replaceAll("", "-")); // 空文字を探す(replaceAll)
-a-
-abc
-a-b-c-
空文字を探すと、replace は先頭に1つ、replaceAll は文字と文字のすき間すべてに挿入します。変数が空文字になりうるときは、if (word) { ... } で先に確かめておくと意図どおりになります。
正規表現のフラグと置換結果の関係
replace と replaceAll の結果は、正規表現に付けるフラグで変わります。全置換に関わるのは g ですが、ほかのフラグも置換の範囲を左右します。同じ入力でフラグだけを変えた結果を並べます。
フラグ別の実行結果
| フラグ | 意味 | コード | 実行結果 |
|---|---|---|---|
| g | すべて置換 | "Abc abc".replace(/abc/g, "x") |
"Abc x" |
| gi | 大文字小文字を区別しない | "Abc abc".replace(/abc/gi, "x") |
"x x" |
| g(m なし) | ^ は文字列の先頭だけ |
"a\nb\nc".replace(/^/g, "> ") |
先頭の1行だけに > が付く |
| gm | ^ が各行の先頭に一致 |
"a\nb\nc".replace(/^/gm, "> ") |
3行すべてに > が付く |
| g(s なし) | 「.」は改行に一致しない | 下のコード | 置換されない |
| gs | 「.」が改行にも一致 | 下のコード | "X" |
| g(u なし) | 絵文字1つが2文字分として数えられる | "😀😀".replace(/./g, "-") |
"----" |
| gu | 絵文字1つを1文字として数える | "😀😀".replace(/./gu, "-") |
"--" |
| y | 現在位置(先頭)からの一致だけ | "aab".replace(/a/y, "-") |
"-ab" |
| gy | 先頭から連続して一致する分だけ | "aab".replace(/a/gy, "-") |
"--b" |
// s フラグ:改行をまたいで一致させる
console.log("<p>a\nb</p>".replace(/<p>.*<\/p>/g, "X")); // s なし
console.log("<p>a\nb</p>".replace(/<p>.*<\/p>/gs, "X")); // s あり
<p>a
b</p>
X
s フラグがないと「.」が改行で止まるため、改行を含むタグは一致せず、元の文字列がそのまま返りました。複数行にまたがる範囲を置換したいときは s フラグ、行ごとに先頭や末尾を置換したいときは m フラグを足します。
各行の先頭に文字を足す
console.log("a\nb\nc".replace(/^/gm, "> "));
> a
> b
> c
引用の記号を付ける、インデントをそろえる、といった処理が1行で書けます。
同じ正規表現オブジェクトをくり返し使うとき
g フラグつきの正規表現オブジェクトは、内部に lastIndex(次に探し始める位置)を持っています。replace は、呼び出すたびに先頭から探し直し、終わると lastIndex を 0 に戻します。
const r = /a/g;
r.lastIndex = 2; // わざと途中の位置にしておく
console.log("aaa".replace(r, "b"), r.lastIndex);
bbb 0
lastIndex を 2 にしておいても、3文字すべてが置換され、lastIndex は 0 に戻りました。replace と replaceAll に渡すぶんには、正規表現を変数に入れて使い回しても結果は変わりません。
そのほかのよく使う置換
| やりたいこと | コード | 実行結果 |
|---|---|---|
| 数字以外を取り除く | "電話: 03-1234-5678".replace(/\D/g, "") |
"0312345678" |
| 前後の空白を取り除く | " 前後の空白 ".replace(/^\s+|\s+$/g, "") |
"前後の空白"(trim() と同じ結果) |
| 複数の記号をまとめて取り除く | "a-b_c d".replace(/[-_ ]/g, "") |
"abcd" |
| 日付の区切りを変える | "2026/10/03".replaceAll("/", "-") |
"2026-10-03" |
| パスの区切りを変える | "C:\\work\\a.txt".replaceAll("\\", "/") |
"C:/work/a.txt" |
| 置換をつなげる | "Hello".replace(/l/g, "L").replace("H", "J") |
"JeLLo" |
split と join を使う全置換との比較
replaceAll が使えるようになる前は、split(探す文字).join(置換後) が全置換の定番でした。いまも有効な書き方で、結果は同じです。
console.log("a.b.c A.B".split(".").join("-")); // a-b-c A-B
| 比べる点 | replaceAll(文字列) | replace(正規表現 g) | split + join |
|---|---|---|---|
| 記号のエスケープ | 不要 | 必要 | 不要 |
| 大文字小文字を無視 | できない | i フラグでできる | できない |
特殊パターン($& など) |
解釈される | 解釈される | 解釈されない |
| コールバック関数 | 使える | 使える | 使えない |
| 読みやすさ | 意図がそのまま伝わる | パターンの知識が必要 | 「分けてつなぐ」と読み替えが必要 |
| 使える環境 | ES2021 以降 | すべて | すべて |
「使える環境」の行は一般に知られた仕様で、TypeScript の lib が es2021 以降で replaceAll の型が通ることは上の章で確認しました。
速度の目安
100万文字(「a.b.」を25万回くり返した文字列)で「.」を全置換し、10回の平均を取りました。Node.js 22.22.2 での1回の計測結果です。
| 方法 | 1回あたりの時間 |
|---|---|
replaceAll(".", "-") |
144.3 ms |
replace(/\./g, "-") |
114.4 ms |
split(".").join("-") |
55.7 ms |
この条件では split + join がいちばん速い結果でした。ただし、文字列の長さや一致の数、実行環境で順位は変わります。数百〜数千文字の置換では差を体感することはまずないので、読みやすさで replaceAll を選ぶのがおすすめです。大きなテキストをくり返し処理する箇所だけ、実際のデータで測って決めるとよいでしょう。
選び方の判断フロー
flowchart TD
A["文字列を置換したい"] --> B{"置換するのは1か所だけ?"}
B -->|1か所| C["replace(文字列)"]
B -->|すべて| D{"探すのは決まった文字列?"}
D -->|決まった文字列| E{"大文字小文字を区別する?"}
D -->|パターン| F["replace か replaceAll + 正規表現(g)"]
E -->|区別する| G["replaceAll(文字列)"]
E -->|区別しない| H["エスケープして new RegExp(…, 'gi')"]
つまずきやすい点のチェックリスト
| 起きること | 原因 | 対処 |
|---|---|---|
| 1か所しか置換されない | replace に文字列、または g なしの正規表現を渡している | replaceAll にするか g を付ける |
| TypeError: … non-global RegExp argument | replaceAll に g なしの正規表現を渡した | g フラグを付ける |
| 置換したのに変数が変わらない | 戻り値を受け取っていない | s = s.replaceAll(…) と入れ直す |
| 関係ない文字まで置換される | 正規表現で「.」などがエスケープされていない | replaceAll に文字列で渡す、またはエスケープ関数を通す |
| SyntaxError: Nothing to repeat | 「?」「+」などをそのまま new RegExp に渡した | エスケープ関数を通す |
| 置換後に「$」が消える・別の文字になる | 置換文字列の $& や $$ が解釈された |
置換後を関数で返す () => to |
| 連続した置換で結果がおかしい | 前の置換結果を次の置換が拾っている | 対応表 + 1回の replace にまとめる |
| xxx.replace is not a function | 対象が数値など文字列以外 | String(value) で文字列にしてから呼ぶ |
よくある質問
Q. replace で全置換するにはどうすればよいですか?
A. 正規表現に g フラグを付けます(例:str.replace(/a/g, "b"))。探す文字列が決まっているなら、str.replaceAll("a", "b") のほうが記号のエスケープを気にせずに書けます。
Q. replaceAll と replace(/…/g) で結果に違いはありますか? A. 同じ正規表現(g つき)を渡した場合、この記事の実行結果では同じでした。違いは、replaceAll は g がないと TypeError で知らせてくれる点と、文字列を渡したときにすべてを置換する点です。
Q. 変数に入った文字列を全置換したいときは?
A. str.replaceAll(word, to) がいちばん簡単です。word に「.」や「?」が含まれていても、文字どおりに探します。大文字小文字を無視したいなど正規表現の機能が必要なときは、エスケープ関数を通してから new RegExp(…, "gi") にします。
Q. RegExp.escape はもう使えますか? A. MDN では Baseline 2025 とされており、Chromium 141 では動作しました。Node.js 22.22.2 では未搭載(typeof が undefined)だったので、Node.js 22 系で動かすコードでは代替のエスケープ関数を用意しておくと確実です。
まとめ
- replace は最初の1か所、replaceAll はすべてを置換する。 replace でも正規表現に g を付ければ全置換になる。
- 決まった文字列の全置換は replaceAll(文字列) がいちばん簡単。 記号のエスケープが要らない。
- replaceAll に g なしの正規表現を渡すと TypeError。 メッセージの文面はエンジンごとに違うが、原因は同じ。
- 置換文字列の中では
$&・$1・$<name>・$$が使える。 「$」をそのまま入れたいときは、置換後を関数で返す。 - コールバックには「一致部分、グループ、位置、元の文字列、名前つきグループ」が渡る。 計算や対応表を使った置換に向く。
- 記号を含む語を正規表現にするときはエスケープする。 RegExp.escape は Chromium 141 で動作、Node.js 22.22.2 では未搭載なので代替関数を用意する。
- 複数語の置換や入れ替えは、対応表と1回の replace にまとめると、置換結果がもう一度置換されるのを防げる。
参考・出典
- MDN Web Docs「String.prototype.replaceAll()」(g フラグなしのときの TypeError の説明)
- MDN Web Docs「RegExp.escape()」(Baseline 2025、エスケープされる文字)
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「JavaScript replaceとreplaceAllの違い|全置換のやり方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。