---
type: reference
language: javascript
slug: array/slice
title: "Array.prototype.slice() と splice()"
title_tag: "JavaScript slice() と splice() の違い — 元が変わるか"
summary: >
  名前が似ている slice() と splice() は、まったく別のものです。取り出すだけか元を書き換えるか、
  引数の意味の違い、負の数の扱い、浅いコピーになる点までを実行して確かめます。
description: >
  名前は似ていても、slice は取り出すだけ、splice は元を書き換えます。第2引数の意味も違います。負の数の扱い、浅いコピーになる点、繰り返しの中で使うと起きる取りこぼしまで扱います。
status: published
difficulty: 2
minutes: 9

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

sources:
  - title: "Array.prototype.slice — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.slice"
  - title: "Array.prototype.splice — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-array.prototype.splice"
  - title: "Array.prototype.toSpliced — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/toSpliced"

terms: [破壊的メソッド, 浅いコピー, 添字]

links:
  related:
    - javascript/learn/array/basics
    - javascript/how-to/array/flatten
    - javascript/reference/array/map
    - javascript/how-to/array/chunk
    - javascript/why/zero-index

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

`slice()` は、配列の一部を**新しい配列にして返します**。[key:元の配列は変わりません]。

```js run
const fruits = ['あ', 'い', 'う', 'え', 'お'];

console.log(fruits.slice(1, 3));
console.log(fruits);
```
```output
[ 'い', 'う' ]
[ 'あ', 'い', 'う', 'え', 'お' ]
```

`splice()` は名前が似ていますが、**元の配列を[bad:書き換えます]**。

```js run
const fruits = ['あ', 'い', 'う', 'え', 'お'];

console.log(fruits.splice(1, 2));
console.log(fruits);
```
```output
[ 'い', 'う' ]
[ 'あ', 'え', 'お' ]
```

**戻り値は同じでも、`fruits` が変わっています。**
文字が1つ違うだけで、まったく別のものです。

| | `slice()` | `splice()` |
|---|---|---|
| 元の配列 | [em:変わらない] | [bad:書き換わる] |
| 第2引数 | **終わりの位置** | **取り除く個数** |
| 戻り値 | 取り出した部分 | 取り除いた部分 |
| 要素を足す | できない | できる |

## `slice(start, end)`

第2引数は[key:終わりの位置]で、**そこは含みません**。

```js run
const fruits = ['あ', 'い', 'う', 'え', 'お'];

console.log(fruits.slice(2));
console.log(fruits.slice(-2));
console.log(fruits.slice());
console.log(fruits.slice(3, 1));
```
```output
[ 'う', 'え', 'お' ]
[ 'え', 'お' ]
[ 'あ', 'い', 'う', 'え', 'お' ]
[]
```

- 省略すると[fn:最後まで]
- 負の数は[key:後ろから数えます]
- 引数なしは**全部の複製**
- `start` が `end` より後ろなら[type:空配列]。[bad:入れ替えてはくれません]

考え方は[文字列の `slice()`](/ja/javascript/learn/string/slice/)と同じです。

### 複製は「浅い」

`slice()` が作るのは新しい配列ですが、**中身は同じものを指しています。**

```js run
const rows = [{ n: 1 }];
const copied = rows.slice();

copied[0].n = 99;

console.log(rows[0].n);
console.log(copied === rows, copied[0] === rows[0]);
```
```output
99
false true
```

配列そのものは別（`false`）でも、**中のオブジェクトは同じ**（`true`）です。
これを[type:浅いコピー]と呼びます。
[bad:複製したつもりで元が変わる]のは、ここが原因であることがほとんどです。

→ [オブジェクトを結合する](/ja/javascript/how-to/object/merge/)

## `splice(start, 削除数, 足すもの...)`

第2引数は[key:取り除く個数]です。位置ではありません。

```js run
const items = ['あ', 'い', 'う'];

console.log(items.splice(1, 0, 'X', 'Y'));
console.log(items);
```
```output
[]
[ 'あ', 'X', 'Y', 'い', 'う' ]
```

削除数を[num:0]にすると、**取り除かずに差し込むだけ**になります。
何も取り除いていないので、戻り値は空配列です。

置き換えもできます。

```js run
const items = ['あ', 'い', 'う'];

console.log(items.splice(1, 1, 'Z'));
console.log(items);
```
```output
[ 'い' ]
[ 'あ', 'Z', 'う' ]
```

削除数を省くと、**そこから後ろが全部消えます。**

```js run
const nums = [1, 2, 3, 4];

console.log(nums.splice(2));
console.log(nums);
```
```output
[ 3, 4 ]
[ 1, 2 ]
```

開始位置には負の数も使えます。

```js run
const nums = [1, 2, 3, 4];

console.log(nums.splice(-2, 1));
console.log(nums);
```
```output
[ 3 ]
[ 1, 2, 4 ]
```

## 元を変えたくないなら `toSpliced()`

`splice()` と同じことを、**元を変えずに**します（ES2023）。

```js run
const nums = [1, 2, 3];

console.log(nums.toSpliced(1, 1));
console.log(nums);
```
```output
[ 1, 3 ]
[ 1, 2, 3 ]
```

[dim:Node 20 / Chrome 110 / Safari 16 より前の環境では使えません。]

## よくある間違い

### `splice()` の第2引数を位置だと思う

```js bad
const fruits = ['あ', 'い', 'う', 'え', 'お'];

console.log(fruits.splice(1, 3));
```
```output
[ 'い', 'う', 'え' ]
```

[num:1]番目から[num:3]番目まで、のつもりが**3個取り除かれています**。
`slice(1, 3)` なら[num:2]個です。**同じ数字を渡しても結果が違います。**

### `splice()` の戻り値を「残り」だと思う

```js bad
const fruits = ['あ', 'い', 'う'];
const rest = fruits.splice(0, 1);

console.log(rest);
```
```output
[ 'あ' ]
```

返るのは[key:取り除いたほう]です。残りは元の配列（`fruits`）に入っています。

### 繰り返しの中で `splice()` する

```js bad
const nums = [1, 2, 2, 3];

for (let i = 0; i < nums.length; i++) {
  if (nums[i] === 2) nums.splice(i, 1);
}

console.log(nums);
```
```output
[ 1, 2, 3 ]
```

**`2` が1つ残りました。**
取り除くと後ろが前に詰まるのに、`i` は進んでしまうので[bad:1つ飛ばして見ています]。

`filter()` を使えば、この問題は起きません。

```js run
const nums = [1, 2, 2, 3];

console.log(nums.filter((n) => n !== 2));
```
```output
[ 1, 3 ]
```

**取り除きたいときは、まず `filter()` を考えてください。**
→ [配列を変換する・絞り込む](/ja/javascript/learn/array/transform/)

## まとめ

- `slice()` は取り出すだけ。**元は変わらない**
- `splice()` は[bad:元を書き換える]。第2引数は**個数**
- `slice()` の複製は[type:浅いコピー]。中のオブジェクトは共有される
- `splice(i, 0, x)` で差し込み、`splice(i, 1, x)` で置き換え
- 元を変えたくないなら `toSpliced()`
- **繰り返しの中で `splice()` しない。** `filter()` を使う
