2024年9月24日

配列のメソッド

配列は多くのメソッドを提供します。分かりやすくするために、このチャプターではグループに分けて説明します。

アイテムの追加/削除

私たちは既に先頭または末尾にアイテムを追加/削除するメソッドを知っています:

  • push(...items)items を末尾に追加します。
  • pop() は末尾の要素を削除し、それを返します。
  • shift() は先頭の要素を削除し、それを返します。
  • unshift(...items) はアイテムを先頭に追加します。

他にもいくつかあります。

splice

配列から要素を削除する方法はどのようになるでしょう?

配列はオブジェクトなので、 delete を試すことができます:

let arr = ["I", "go", "home"];

delete arr[1]; // "go" を削除

alert( arr[1] ); // undefined

// now arr = ["I",  , "home"];
alert( arr.length ); // 3

要素は削除されましたが、配列は依然として3つの要素を持っており、arr.length == 3 となります。

これは自然なことです。なぜなら、 delete obj.keykey で値を削除するためのものです。それがすべてであり、オブジェクトでは問題ありません。しかし、通常配列では残りの要素が移動し、解放された場所を埋めたいです。今より短い配列になることを期待しています。

なので、特別なメソッドを使用する必要があります。

arr.splice(str) メソッドは、配列用のスイス製アーミーナイフです。それは何でもすることができます: 追加、削除、また要素の挿入も。

構文:

arr.splice(index[, deleteCount, elem1, ..., elemN])

位置 index から始まります。 deleteCount の要素を削除した後、その場所に elem1, ..., elemN を挿入します。このメソッドは削除した要素の配列を返します。

このメソッドは例で簡単に把握できます。

削除してみましょう:

let arr = ["I", "study", "JavaScript"];

arr.splice(1, 1); // インデックス 1 から 1 要素を削除

alert( arr ); // ["I", "JavaScript"]

簡単ですね。インデックス 1 から始まり、1 つ要素を削除します。

次の例では、3つの要素を削除し、他の2つの要素でそれらを置き換えます:

let arr = ["I", "study", "JavaScript", "right", "now"];

// 最初の 3 要素を削除し、別のものに置換
arr.splice(0, 3, "Let's", "dance");

alert( arr ) // 今は ["Let's", "dance", "right", "now"]

ここで、splice が削除された要素の配列を返していることを見ることができます:

let arr = ["I", "study", "JavaScript", "right", "now"];

// 最初の 2 要素を削除
let removed = arr.splice(0, 2);

alert( removed ); // "I", "study" <-- 削除された要素の配列

splice メソッドは削除せずに挿入することも可能です。そのためには、deleteCount0 をセットします:

let arr = ["I", "study", "JavaScript"];

// インデックス 2 から
// 削除 0
// その後 "complex" と "language" を挿入
arr.splice(2, 0, "complex", "language");

alert( arr ); // "I", "study", "complex", "language", "JavaScript"
負のインデックスも許容します

上記や他の配列のメソッドでは、負のインデックスが許容されます。それらは配列の末尾からの位置を指定します。:

let arr = [1, 2, 5];

// インデックス -1 (末尾から1つ前) から
// 削除 0 要素,
// その後 3 と 4 を挿入
arr.splice(-1, 0, 3, 4);

alert( arr ); // 1,2,3,4,5

slice

メソッド arr.slice は似たように見える arr.splice よりもはるかに単純です。

構文:

arr.slice(start, end)

開始インデックス "start" から "end" ("end" は含みません)のすべてのアイテムをコピーした新しい配列を返します。startend はともに負値になることができます。そのときは、配列の末尾からの位置が想定されます。

str.slice のように動作しますが、部分文字列の代わりに部分配列を作ります。

例:

let arr = ["t", "e", "s", "t"];

alert( arr.slice(1, 3) ); // e,s (1 から 3 をコピー)

alert( arr.slice(-2) ); // s,t (-2 から末尾まで)

引数なし arr.slice() でも呼び出すことができ、これは arr のコピーを生成します。これは、オリジナルの配列に影響を与えない形でさらに変換するためのためのコピーを取得するのによく使用されます。

concat

メソッド arr.concat は配列を他の配列またはアイテムと結合します。

構文:

arr.concat(arg1, arg2...)

任意の数の引数(配列または値)を許容します。

結果は arr, 次に arg1, arg2 などのアイテムを含む新しい配列を返します。

もし、引数が配列、もしくは Symbol.isConcatSpreadable プロパティを持っている場合、その全ての要素がコピーされます。そうでない場合、引数自体がコピーされます。

例:

let arr = [1, 2];

// arr と [3,4] をマージ
alert( arr.concat([3, 4])); // 1,2,3,4

// arr と [3,4] と [5,6] をマージ
alert( arr.concat([3, 4], [5, 6])); // 1,2,3,4,5,6

// arr と [3,4] をマージ後, 5 と 6 を追加
alert( arr.concat([3, 4], 5, 6)); // 1,2,3,4,5,6

通常は、配列から要素をコピーするだけです。それ以外のオブジェクトでは、配列のように見えたとしても、全体として追加されます:

let arr = [1, 2];

let arrayLike = {
  0: "something",
  length: 1
};

alert( arr.concat(arrayLike) ); // 1,2,[object Object]

…しかし、もし配列のようなオブジェクトが Symbol.isConcatSpreadable プロパティを持つ場合、concat は配列として扱います。つまり、代わりにその要素が追加されます:

let arr = [1, 2];

let arrayLike = {
  0: "something",
  1: "else",
  [Symbol.isConcatSpreadable]: true,
  length: 2
};

alert( arr.concat(arrayLike) ); // 1,2,something,else

イテレート/反復: forEach