Array.prototype.slice() と splice()

名前が似ている slice() と splice() は、まったく別のものです。取り出すだけか元を書き換えるか、引数の意味の違い、負の数の扱い、浅いコピーになる点までを実行して確かめます。

実行して検証済み処理系Node 22.22.3対応ES3難易度●●○○○目安9更新

slice() は、配列の一部を新しい配列にして返します元の配列は変わりません

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'い', 'う' ] [ 'あ', 'い', 'う', 'え', 'お' ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'い', 'う' ] [ 'あ', 'え', 'お' ]

splice() は名前が似ていますが、元の配列を書き換えます

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'う', 'え', 'お' ] [ 'え', 'お' ] [ 'あ', 'い', 'う', 'え', 'お' ] []
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
99 false true

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

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

slice(start, end)

第2引数は終わりの位置で、そこは含みません

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[] [ 'あ', 'X', 'Y', 'い', 'う' ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'い' ] [ 'あ', 'Z', 'う' ]
  • 省略すると最後まで
  • 負の数は後ろから数えます
  • 引数なしは全部の複製
  • startend より後ろなら空配列入れ替えてはくれません

考え方は文字列の slice()と同じです。

複製は「浅い」

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

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 3, 4 ] [ 1, 2 ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 3 ] [ 1, 2, 4 ]

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

オブジェクトを結合する

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

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

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 3 ] [ 1, 2, 3 ]
javascript
const fruits = ['あ', 'い', 'う', 'え', 'お'];

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

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

置き換えもできます。

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

console.log(rest);
[ 'あ' ]
javascript
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);
[ 1, 2, 3 ]

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

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 1, 3 ]

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

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

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

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

よくある間違い

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

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

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

返るのは取り除いたほうです。残りは元の配列(fruits)に入っています。

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

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

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

取り除きたいときは、まず filter() を考えてください。配列を変換する・絞り込む

まとめ

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

この記事の根拠

  1. Array.prototype.slice — ECMAScript® 2026 Language Specificationtc39.es
  2. Array.prototype.splice — ECMAScript® 2026 Language Specificationtc39.es
  3. Array.prototype.toSpliced — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)