---
type: reference
language: javascript
slug: string/replace
title: "String.prototype.replace() と replaceAll()"
title_tag: "JavaScript replace() の使い方 — 1つだけ置換される理由"
summary: >
  replace() は文字列を渡すと最初の1つしか置き換えません。全部置き換える書き方、
  $ が特別扱いされる落とし穴、関数で置き換える方法までを実行して確かめます。
description: >
  文字列を渡すと最初の1つしか置き換わりません。全部置き換える書き方、置換文字列の $ が特別扱いされる落とし穴、関数で置き換える方法まで実行して示します。
status: published
difficulty: 2
minutes: 8

versions:
  verified: "Node 22.22.3"
  since: "ES1"
  deprecated: null
  removed: null

sources:
  - title: "String.prototype.replace — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-string.prototype.replace"
  - title: "String.prototype.replaceAll — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-string.prototype.replaceall"
  - title: "String.prototype.replace() — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace"

terms: [正規表現, グローバルフラグ, キャプチャ]

links:
  related:
    - javascript/learn/string/search
    - javascript/reference/string/split
    - javascript/errors/is-not-a-function
    - javascript/reference/regexp/test-match

content_updated_at: 2026-09-07
published_at: 2026-09-07
---

`replace()` に文字列を渡すと、**最初に見つかった1つだけ**が置き換わります。
全部置き換えたいなら `replaceAll()` です。

```js run
const text = 'a-b-c';

console.log(text.replace('-', '+'));
console.log(text.replaceAll('-', '+'));
console.log(text);
```
```output
a+b-c
a+b+c
a-b-c
```

元の文字列は変わりません。**戻り値を受け取ってください。**

上のコードは書き換えて実行できます。`'-'` を `'b'` にしてみてください。

## 何を渡せるか

| 第1引数 | 置き換わる数 |
|---|---|
| 文字列（`replace`） | [bad:最初の1つだけ] |
| 文字列（`replaceAll`） | [em:全部] |
| 正規表現（`g` なし） | [bad:最初の1つだけ] |
| 正規表現（`g` あり） | [em:全部] |

```js run
const text = 'a-b-c';

console.log(text.replace(/-/, '+'));
console.log(text.replace(/-/g, '+'));
console.log(text.replaceAll(/-/g, '+'));
```
```output
a+b-c
a+b+c
a+b+c
```

**`replaceAll()` に正規表現を渡すときは `g` が必須**です。
無いと例外になります。

```js bad
console.log('a-b'.replaceAll(/-/, '+'));
```
```output
TypeError: String.prototype.replaceAll called with a non-global RegExp argument
```

## $ が特別扱いされる

置き換える側の文字列に `$` があると、**そのまま入りません。**
`$&` は「一致した部分」という意味を持ちます。

```js bad
console.log('価格'.replace('価格', '$&$&'));
console.log('a'.replace('a', '$$'));
console.log('a'.replace('a', '100$'));
```
```output
価格価格
$
100$
```

| 書き方 | 入るもの |
|---|---|
| `$$` | `$` [num:1]文字 |
| `$&` | 一致した部分 |
| `` $` `` | 一致した部分より前 |
| `$'` | 一致した部分より後ろ |
| `$1` `$2` … | [type:キャプチャ]した部分 |

**利用者が入力した文字を置き換える側に渡すときは、これが事故になります。**

```js bad
const userInput = "$&$&$&";

console.log('ここ'.replace('ここ', userInput));
```
```output
ここここここ
```

入れたはずの文字と違うものが出ました。

### 直しかた

**関数を渡します。** 関数の戻り値は[key:そのまま入ります]。

```js run
const userInput = "$&$&$&";

console.log('ここ'.replace('ここ', () => userInput));
```
```output
$&$&$&
```

`$` を自分で書ける形にしたいなら、`$$` に置き換えてから渡します。

```js run
const userInput = "100$";

console.log('X'.replace('X', userInput.replaceAll('$', '$$$$')));
```
```output
100$
```

[dim:$$$$ が $$ 2つぶんで、結果として $ 1文字になります。読みにくいので、関数を渡すほうを勧めます。]

## 関数で置き換える

関数には[key:一致した文字列]が渡ります。位置ごとに違う結果を返せます。

```js run
const text = 'a1b22c333';

console.log(text.replace(/\d+/g, (m) => `[${m.length}桁]`));
```
```output
a[1桁]b[2桁]c[3桁]
```

キャプチャした部分は[num:2]つ目以降の引数で受け取ります。

```js run
const text = '2026-09-07';

console.log(text.replace(/(\d{4})-(\d{2})-(\d{2})/, (m, y, mo, d) => `${y}年${mo}月${d}日`));
```
```output
2026年09月07日
```

`09` と `07` のまま出ています。**関数の中で好きに直せる**のが、文字列で書く場合との違いです。

```js run
const text = '2026-09-07';

console.log(text.replace(/(\d{4})-(\d{2})-(\d{2})/, (m, y, mo, d) => `${y}年${Number(mo)}月${Number(d)}日`));
```
```output
2026年9月7日
```

文字列で書くなら `$1` `$2` を使います。**こちらのほうが短く読めます。**

```js run
console.log('2026-09-07'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$1年$2月$3日'));
```
```output
2026年09月07日
```

## 名前付きキャプチャ

数字より、名前のほうが読めます。

```js run
const text = '2026-09-07';
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

console.log(text.replace(re, '$<year>/$<month>/$<day>'));
console.log(text.match(re).groups.year);
```
```output
2026/09/07
2026
```

## 正規表現の特殊文字に気をつける

利用者の入力を**第1引数に**渡すときも注意が要ります。
`replaceAll()` に文字列を渡すぶんには安全ですが、正規表現にすると意味が変わります。

```js bad
const keyword = 'a.c';

console.log('abc axc a.c'.replaceAll(keyword, '■'));
console.log('abc axc a.c'.replace(new RegExp(keyword, 'g'), '■'));
```
```output
abc axc ■
■ ■ ■
```

`.` が[bad:任意の1文字]として扱われ、`abc` も `axc` も消えました。

**文字列で済むなら `replaceAll()` に文字列を渡してください。**
正規表現にする必要があるなら、先に逃がします。

```js run
function escapeRe(s) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

const keyword = 'a.c';

console.log(escapeRe(keyword));
console.log('abc axc a.c'.replace(new RegExp(escapeRe(keyword), 'g'), '■'));
```
```output
a\.c
abc axc ■
```

## 大文字と小文字を無視する

`i` フラグを付けます。文字列を渡す方法では[bad:できません]。

```js run
const text = 'Apple apple APPLE';

console.log(text.replaceAll('apple', '■'));
console.log(text.replace(/apple/gi, '■'));
```
```output
Apple ■ APPLE
■ ■ ■
```

## g フラグ付きの正規表現を使い回さない

`g` を付けた正規表現は[key:内部に位置を覚えます]。
`replace()` は使うたびに戻しますが、`test()` や `exec()` は[bad:戻しません]。

```js bad
const re = /a/g;

console.log(re.test('abc'));
console.log(re.test('abc'));
console.log(re.lastIndex);
```
```output
true
false
0
```

**同じ文字列を調べたのに、2回目は false**です。
[num:1]回目で位置が進み、[num:2]回目は最後まで行って `0` に戻ったところです。

判定に使うなら `g` を外すか、毎回作り直してください。

```js run
console.log(/a/.test('abc'));
console.log(/a/.test('abc'));
```
```output
true
true
```

分割の話は
[String.prototype.split()](/ja/javascript/reference/string/split/) にまとめてあります。

置き換えではなく「探すだけ」「分けるだけ」で足りる場面も多くあります。判断の目安はこちらです。
→ [文字列を探す・分ける・置き換える](/ja/javascript/learn/string/search/)
