Array

Array オブジェクトは、他のプログラミング言語の配列と同様に、複数の項目の集合を単一の変数名の下に格納することができ、共通の配列操作を行うためのメンバーを持っています。

解説

JavaScript では、配列はプリミティブではなく、主に次のような性質を持つ Array オブジェクトです。

  • JavaScript の配列はリサイズ可能であり、異なるデータ型を交ぜて格納することができます。(これらの性質が望ましくない場合は、代わりに型付き配列を使用してください)。
  • JavaScript の配列は連想配列ではありません。配列の要素はインデックスとして任意の文字列を使用してアクセスすることができません。非負の整数(またはそれぞれの文字列表現)をインデックスとして使用してアクセスする必要があります。
  • JavaScript の配列はゼロオリジンです。配列の最初の要素は 0 の位置にあり、 2 番目の要素は 1 の位置にあるといった具合です。そして、最後の要素は配列の length プロパティの値から 1 を引いた位置になります。
  • JavaScript の配列コピー操作シャローコピーを生成します。(JavaScript オブジェクトに対するすべての標準組み込みコピー操作は、ディープコピーではなく、シャローコピーを作成します)。

配列のインデックス

Array オブジェクトは要素のインデックスとして任意の文字列を(連想配列のように)使用することはできません。非負の整数(またはその文字列形式)を使用しなければなりません。整数以外の値で設定したりアクセスしたりすると、配列のリスト自体の要素を設定したり取り出したりすることはできませんが、その配列のオブジェクトプロパティの集合に関連する変数を設定したりアクセスしたりすることができます。配列のオブジェクトプロパティと配列要素のリストは別個のものであり、配列の探索や変更操作はこれらの名前付きプロパティに適用することができません。

toString が一つのプロパティであるのと同様に(ただし厳密には toString() はメソッドですが)、配列における配列要素はオブジェクトのプロパティです。しかし、次のように配列にアクセスしようとすると、プロパティ名が妥当でないため、構文エラーが発生します。

js
arr.0; // 構文エラー

JavaScript の構文では、数字で始まるプロパティにはブラケット記法を使う必要があり、ドット記法を使うことはできません。また、配列のインデックスを引用符で囲むことができますが(years[2] の代わりに years['2'] のように)、ふつうはそうする必要はありません。

years[2]2 は最終的に、JavaScript エンジンが内部的に toString メソッドで型変換することで文字列にされます。これは '2' と '02' が years オブジェクトの異なる場所を指すようにするためでです。このため、以下の例は true がログ出力されます。

js
console.log(years["2"] !== years["02"]);

years['2'] だけが実際の配列のインデックスです。 years['02'] は自由な文字列のプロパティであり、配列の反復処理では処理されません。

length と数値プロパティとの関係

JavaScript の配列の length プロパティと数値プロパティは関連しています。

配列の一部の組込みメソッド(例えば join(), slice(), indexOf(), など)は、配列の length プロパティの値はメソッドの呼び出し時の値を考慮します。

他にも(例えば push(), splice(), など)、結果として配列の length プロパティを更新するメソッドがあります。

js
const fruits = [];
fruits.push("バナナ", "りんご", "もも");
console.log(fruits.length); // 3

JavaScript の配列で、配列のインデックスとして妥当なプロパティであり、かつ現在の配列の範囲の外にあるインデックスを設定すると、エンジンは配列の length プロパティを更新します。

js
fruits[5] = "マンゴー";
console.log(fruits[5]); // "マンゴー"
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 6

length を増やすと、 undefined でもなく、新しい要素を作成せずに空のスロットを追加して配列を拡張します。

js
fruits.length = 10;
console.log(fruits); // ['バナナ', 'りんご', 'もも', 空 x 2, 'マンゴー', 空 x 4]
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 10
console.log(fruits[8]); // undefined

一方、 length プロパティの数を減らすと、要素が削除されます。

js
fruits.length = 2;
console.log(Object.keys(fruits)); // ['0', '1']
console.log(fruits.length); // 2

これらについては Array/length のページで詳しく解説します。

配列メソッドと空のスロット

疎配列において空のスロットは、配列のメソッド間で一貫性のない動作をします。一般に、古いメソッドは空のスロットをスキップしますが、新しいメソッドはそれを undefined として扱う傾向があります。

複数の要素を反復処理するメソッドのうち、以下のものはインデックスにアクセスする前に in によるチェックを行い、空のスロットと undefined を混同しないようにします。

空のスロットを具体的にどのように扱うかについては、各メソッドのページを参照してください。

以下のメソッドは、空のスロットを undefined であるかのように扱います。

コピーメソッドと変更メソッド

メソッドの中には、呼び出された既存の配列を変更せずに新しい配列を返すものもあります。その場合は、まず新しい配列を作成し、そこに要素を代入します。コピーは常にシャローコピーで行われ、メソッドは最初に作成された配列以外をコピーすることはありません。元の配列の要素は、次のように新しい配列にコピーされます。

  • オブジェクトの場合は、オブジェクトの参照が新しい配列にコピーされます。元の配列と新しい配列の両方が同じオブジェクトを参照します。つまり、参照するオブジェクトが変更された場合、その変更は新しい配列と元の配列の両方に反映されます。
  • 文字列、数値、論理値などのプリミティブ型(String, Number, Boolean オブジェクトではないもの)の場合、値は新しい配列へコピーされます。

他にも、メソッドが呼び出された配列を変更するメソッドがあります。この場合、メソッドによって返値が異なります。あるものは同じ配列への参照を、あるものは新しい配列の長さを返します。

以下のメソッドは、 this.constructor[Symbol.species] にアクセスして使用するコンストラクターを決定し、新しい配列を作成します。

以下のメソッドは常に Array ベースのコンストラクターで新しい配列を作成します。

以下の表は、元の配列を変更メソッドと、それに対応する変更しない代替メソッドの一覧です。

変更メソッド 変更しない代替メソッド
copyWithin() 代替メソッドなし
fill() 代替メソッドなし
pop() slice(0, -1)
push(v1, v2) concat([v1, v2])
reverse() toReversed()
shift() slice(1)
sort() toSorted()
splice() toSpliced()
unshift(v1, v2) toSpliced(0, 0, v1, v2)

変更メソッドを変更しない代替メソッドに変更する簡単な方法は、スプレッド構文slice() を使って最初にコピーを作成することです。

js
arr.copyWithin(0, 1, 2); // arr を変更
const arr2 = arr.slice().copyWithin(0, 1, 2); // arr を変更しない
const arr3 = [...arr].copyWithin(0, 1, 2); // arr を変更しない

反復処理メソッド

多くの配列メソッドは、コールバック関数を引数にとります。コールバック関数は配列のそれぞれの要素に対して順次、最大1回呼び出され、コールバック関数の返値はメソッドの返値を決定するために使用されます。これらはすべて同じ形式です。

js
method(callbackFn, thisArg)

callbackFn は 3 つの引数を取ります。

element

配列の中で現在処理されている要素。

index

配列の中で、現在処理中の要素のインデックス。

array

メソッドが呼び出された配列。

callbackFn が何を返すかは、呼び出された配列メソッドによって異なります。

引数 thisArg (既定値は undefined)は、callbackFn を呼び出す際に this 値として使用されます。callbackFn から最終的に見える this 値は、通常のルールに従って決定します。もし callbackFn厳格モードではないのであれば、this の値がプリミティブ型であった場合はオブジェクトにラップされ、undefined/null の場合は globalThis に置き換わります。callbackFnアロー関数で定義されていた場合は、thisArg 引数は関係ありません。アロー関数には自分自身の thisバインディングがないためです。

すべての反復可能オブジェクトはコピー可能汎用性がありますが、空のスロットでは異なる形で動作します。

以下のメソッドは反復可能です。

具体的には、every(), find(), findIndex(), findLast(), findLastIndex(), some() は常にすべての要素に対して callbackFn を呼び出すわけではなく、返値が決定するとすぐに反復処理を停止します。

他にもコールバック関数を受け取り、配列のそれぞれの要素に対して最大1回実行するメソッドが2種類ありますが、一般的な反復処理メソッドとは少し異なる形式を持っています(thisArg を受け入れないなど)。

sort() メソッドもコールバック関数を取りますが、反復処理するメソッドではありません。配列の配置を変更し、thisArg を受け入れず、1 つのインデックスに対して複数回コールバックを呼び出すことがあります。

汎用的な配列メソッド

配列メソッドは常に汎用的であり、配列オブジェクトの内部データにはアクセスしません。配列の要素には length プロパティを通してアクセスし、インデックスの要素にはアクセスするだけです。つまり、配列風のオブジェクトに対しても呼び出すことができます。

js
const arrayLike = {
  0: "a",
  1: "b",
  length: 2,
};
console.log(Array.prototype.join.call(arrayLike, "+")); // 'a+b'

length プロパティの正規化

length プロパティは数値に変換され、0 から 253 - 1 までの範囲に収められます。NaN0 となるので、length が存在しないか undefined であっても 0 という値を持つものとして扱われます。

言語は length安全でない整数に設定することを避けます。もし length が 253 - 1 より大きい数に設定されると、すべての組み込みメソッドは TypeError を発生させます。しかし、配列の length プロパティは、232 - 1 より大きい値に設定されるとエラーが発生するので、メソッドが非配列オブジェクトで呼び出されない限り、安全な整数のしきい値に達することは通常ありません。

js
Array.prototype.flat.call({}); // []

配列メソッドの中には、配列オブジェクトの length プロパティを設定するものがあります。これらのメソッドは常に正規化後の値を設定するので、length は常に整数値になります。

js
const a = { length: 0.7 };
Array.prototype.push.call(a);
console.log(a.length); // 0

配列風オブジェクト

配列風オブジェクトとは、上記の length の処理で例外が発生しないオブジェクトのことです。具体的に言うと、このようなオブジェクトには実際に length プロパティがあり、0 から length - 1 までのインデックスつき要素を持つことが期待されます(すべてのインデックスが存在するわけではない場合は、機能的に疎配列と同等となります)。配列メソッドが配列風オブジェクトを処理するとき、 0 より小さいか length - 1 より大きい整数インデックスは無視されます。

多くの DOM オブジェクトは、例えば NodeListHTMLCollection は配列風です。また、arguments オブジェクトも配列風です。自分自身に配列メソッドがなくても、その配列メソッドを呼び出すことができます。

js
function f() {
  console.log(Array.prototype.join.call(arguments, "+"));
}

f("a", "b"); // 'a+b'

コンストラクター

Array()

新しい Array オブジェクトを生成します。

静的プロパティ

Array[@@species]

Array コンストラクターを返します。

静的メソッド

Array.from()

新しい Array インスタンスを反復可能 (iterable) または配列風 (array-like) オブジェクトから生成します。

Array.fromAsync()

非同期反復可能、反復可能、配列風オブジェクトを元に、新しい Array インスタンスを作成します。

Array.isArray()

配列であれば true を、配列でなければ false を返します。

Array.of()

可変個の引数から、引数の個数や型に関わらず、新しい Array インスタンスを生成します。

インスタンスプロパティ

これらのプロパティは Array.prototype で定義されており、すべての Array インスタンスで共有されます。

Array.prototype.constructor

このインスタンスオブジェクトを作成したコンストラクター関数です。 Array インスタンスの場合、初期値は Array コンストラクターです。

Array.prototype[@@unscopables]

ES2015 版以前の ECMAScript 標準に含まれておらず、 with による文のバインドの目的には無視されるプロパティ名を含みます。

これらのプロパティはそれぞれの Array インスタンスが自分自身で持つプロパティです。

length

配列内の要素数を反映します。

インスタンスメソッド

Array.prototype.at()

指定された位置にある配列の項目を返します。負の整数も指定可能で、末尾の項目から戻ります。

Array.prototype.concat()

この配列に他の配列や値を結合して新しい配列を返します。

Array.prototype.copyWithin()

配列内で配列内の連続した要素を複写します。

Array.prototype.entries()

新しい配列イテレーターオブジェクトを返します。このオブジェクトは、配列中のそれぞれの位置に対するキー/値の組を保持しています。

Array.prototype.every()

指定したテスト関数を配列中のすべての要素が満たした場合に true を返します。

Array.prototype.fill()

配列内の指定した開始位置から終了位置までの要素を固定値で埋めます。

Array.prototype.filter()

指定したフィルタリング関数が true を返す、配列中の要素を格納した新しい配列を生成します。

Array.prototype.find()

指定されたたテスト関数を満たす、配列の最初の要素の値を返します。適切な要素が見つからなかった場合は undefined を返します。

Array.prototype.findIndex()

指定されたテスト関数を満たす、配列の最初の要素のインデックスを返します。適切な要素が見つからなかった場合は -1 を返します。

Array.prototype.findLast()

指定されたたテスト関数を満たす、配列の最後の要素の値を返します。適切な要素が見つからなかった場合は undefined を返します。

Array.prototype.findLastIndex()

指定されたテスト関数を満たす、配列の最後の要素のインデックスを返します。適切な要素が見つからなかった場合は -1 を返します。

Array.prototype.flat()

すべての部分配列の要素を指定された深さまで再帰的に連結した新しい配列を返します。

Array.prototype.flatMap()

コールバック関数を呼び出し元の配列の各要素に適用し、その結果を一段階平坦化した新しい配列を返します。

Array.prototype.forEach()

配列中のそれぞれの要素について関数を呼び出します。

Array.prototype.includes()

この配列が特定の要素を含むかどうか判定し、その結果を true または false で返します。

Array.prototype.indexOf()

指定された値と等しい値を持つ最初の(インデックスの一番小さい)要素のインデックスを返します。見つからない場合、-1 を返します。

Array.prototype.join()

配列のすべての要素を結合した文字列を返します。

Array.prototype.keys()

新しい配列イテレーターを返します。このオブジェクトは配列中の各インデックスのキーを保持します。

Array.prototype.lastIndexOf()

指定された値と等しい値を持つ最後の (インデックスの一番大きい) 要素のインデックスを返します。見つからない場合、-1 を返します。

Array.prototype.map()

配列内のすべての要素に対して与えられた関数を呼び出し、その結果を格納した新しい配列を生成します。

Array.prototype.pop()

配列から最後の要素を取り除き、返値として返します。

Array.prototype.push()

配列の最後に 1 個以上の要素を追加し、新しい配列の length を返します。

Array.prototype.reduce()

アキュムレーターと配列内のすべての要素に対して (左から右の順で) 関数を適用し、単一の値に還元します。

Array.prototype.reduceRight()

アキュムレーターと配列内のすべての要素に対して (右から左の順で) 関数を適用し、単一の値に還元します。

Array.prototype.reverse()

配列の要素の順番を逆転させます (最初の要素は最後に、最後の要素は最初になります)。

Array.prototype.shift()

配列から最初の要素を取り除き、その要素を返します。

Array.prototype.slice()

配列の一部を取り出して新しい配列として返します。

Array.prototype.some()

指定したテスト関数を配列中の少なくとも 1 個の要素が満たした場合に true を返します。

Array.prototype.sort()

配列内で要素を整列し、配列を返します。

Array.prototype.splice()

配列に対して複数の要素を追加したり取り除いたりします。

Array.prototype.toLocaleString()

配列とその要素を表すロケールに従った文字列を返します。Object.prototype.toLocaleString() メソッドを上書きします。

Array.prototype.toReversed()

元の配列を変更せずに、要素を逆順に並べた新しい配列を返します。

Array.prototype.toSorted()

元の配列を変更せずに、要素を昇順に並べた新しい配列を返します。

Array.prototype.toSpliced()

元配列を変更することなく、指定された位置の要素を除去または置き換えた新しい配列を返します。

Array.prototype.toString()

配列とその要素を表す文字列を返します。Object.prototype.toString() メソッドを上書きしています。

Array.prototype.unshift()

配列の最初に 1 個以上の要素を追加し、配列の変更後の length を返します。

Array.prototype.values()

新しい配列イテレーターオブジェクトを返します。このオブジェクトは、配列中の各インデックスの値を保持します。

Array.prototype.with()

指定された位置の要素を指定された値で置き換えた新しい配列を、元の配列に変更を加えることなく返します。

Array.prototype[@@iterator]()

既定では values() 関数を返します。

この節では、 JavaScript で一般的な配列操作の例をいくつか紹介します。

メモ: まだ配列の基本に慣れていない場合は、最初に JavaScript の第一歩: 配列配列とは何かの説明、およびよくある配列の操作の他の例を読んでみてください。

配列の作成

ここでは、新しい配列を作る 3 通りの方法を示しています。最初のものは配列リテラル記法を使用したもので、次は Array() コンストラクターを使用して、最後は String.prototype.split() を使用して文字列から配列を構築しています。

js
// 'fruits' 配列が配列リテラル記法で作成されています。
const fruits = ["りんご", "バナナ"];
console.log(fruits.length);
// 2

// 'fruits2' 配列が Array() コンストラクターで作成されています。
const fruits2 = new Array("りんご", "バナナ");
console.log(fruits2.length);
// 2

// 'fruits3' 配列が String.prototype.split() を使用して作成されています。
const fruits3 = "りんご, バナナ".split(", ");
console.log(fruits3.length);
// 2

配列から文字列を生成

この例では join() メソッドを使用して、配列 fruits から文字列を生成しています。

js
const fruits = ["りんご", "バナナ"];
const fruitsString = fruits.join(", ");
console.log(fruitsString);
// "りんご, バナナ"

インデックスによる配列の要素へのアクセス

この例では配列 fruits 内の項目に、配列内の位置を示すインデックスを指定することでアクセスする方法を示しています。

js
const fruits = ["りんご", "バナナ"];

// 配列の最初の要素のインデックスは必ず 0 です。
fruits[0]; // りんご

// 配列の 2 番目の要素のインデックスは必ず 1 です。
fruits[1]; // バナナ

// 配列の末尾の要素のインデックスは、常に配列の長さよりも
// 1 だけ小さいものです。
fruits[fruits.length - 1]; // バナナ

// 配列の長さよりも大きなインデックスを使用すると、
// 'undefined' が返されます。
fruits[99]; // undefined

配列内の項目のインデックスを検索

この例では indexOf() メソッドを使用して、文字列 "バナナ" の位置(インデックス)を配列 fruits の中から探します。

js
const fruits = ["りんご", "バナナ"];
console.log(fruits.indexOf("バナナ"));
// 1

配列内に特定の項目があるかどうかを検査

この例では、配列 fruits"バナナ""さくらんぼ" を含んでいるかどうかを確認する 2 つの方法を示しています。最初は includes() メソッドで、次に indexOf() メソッドで、インデックスの値が -1 でないことを確認します。

js
const fruits = ["りんご", "バナナ"];

fruits.includes("バナナ"); // true
fruits.includes("さくらんぼ"); // false

// indexOf() が -1 を返さない場合、その配列はその項目を持っています。
fruits.indexOf("バナナ") !== -1; // true
fruits.indexOf("さくらんぼ") !== -1; // false

配列に項目を追加

この例では、 push() メソッドを使用して新しい文字列を配列 fruits に追加しています。

js
const fruits = ["りんご", "バナナ"];
const newLength = fruits.push("みかん");
console.log(fruits);
// ["りんご", "バナナ", "みかん"]
console.log(newLength);
// 3

配列から最後の項目を取り除く

この例では、 pop() メソッドを使用して配列 fruits から最後の項目を取り除いています。

js
const fruits = ["りんご", "バナナ", "みかん"];
const removedItem = fruits.pop();
console.log(fruits);
// ["りんご", "バナナ"]
console.log(removedItem);
// みかん

メモ: pop() は配列の最後の項目を削除するためだけに使用できます。配列の最後にある複数の項目を削除したい場合は、次の例を参照してください。

配列の最後から複数の項目を取り除く

この例では splice() メソッドを使用して、配列 fruits から最後の 3 つの項目を取り除いています。

js
const fruits = ["りんご", "バナナ", "いちご", "マンゴー", "さくらんぼ"];
const start = -3;
const removedItems = fruits.splice(start);
console.log(fruits);
// ["りんご", "バナナ"]
console.log(removedItems);
// ["いちご", "マンゴー", "さくらんぼ"]

配列を最初の N 項目ちょうどに切り詰める

この例では splice() メソッドはを使用して、配列 fruits を最初の 2 項目ちょうどに切り詰めます。

js
const fruits = ["りんご", "バナナ", "いちご", "マンゴー", "さくらんぼ"];
const start = 2;
const removedItems = fruits.splice(start);
console.log(fruits);
// ["りんご", "バナナ"]
console.log(removedItems);
// ["いちご", "マンゴー", "さくらんぼ"]

配列の最初から項目を取り除く

この例では shift() メソッドを使用して、最初の項目を配列 fruits から取り除きます。

js
const fruits = ["りんご", "バナナ"];
const removedItem = fruits.shift();
console.log(fruits);
// ["バナナ"]
console.log(removedItem);
// りんご

メモ: shift() は最初の項目を配列から取り除く場合にのみ使用できます。複数の項目を配列の先頭から取り除く場合は、次の例を参照してください。

配列の先頭から複数の項目を取り除く

この例では splice() メソッドを使用して、配列 fruits から先頭の 3 項目を取り除きます。

js
const fruits = ["りんご", "いちご", "さくらんぼ", "バナナ", "マンゴー"];
const start = 0;
const deleteCount = 3;
const removedItems = fruits.splice(start, deleteCount);
console.log(fruits);
// ["バナナ", "マンゴー"]
console.log(removedItems);
// ["りんご", "いちご", "さくらんぼ"]

配列に最初の項目を追加

この例では unshift() メソッドを使用して、配列 fruits のインデックス 0 に新しい項目を追加します。これを配列の新しい先頭の項目にします。

js
const fruits = ["バナナ", "マンゴー"];
const newLength = fruits.unshift("いちご");
console.log(fruits);
// ["いちご", "バナナ", "マンゴー"]
console.log(newLength);
// 3

インデックスを指定して単一の項目を取り除く

この例では splice() メソッドを使用して、文字列 "バナナ" を配列 fruits から取り除きます。 "バナナ" の位置のインデックスを指定します。

js
const fruits = ["いちご", "バナナ", "マンゴー"];
const start = fruits.indexOf("バナナ");
const deleteCount = 1;
const removedItems = fruits.splice(start, deleteCount);
console.log(fruits);
// ["いちご", "マンゴー"]
console.log(removedItems);
// ["バナナ"]

インデックスを指定して複数の項目を取り除く

この例では splice() メソッドを使用して、文字列 "バナナ" および "いちご" を配列 fruits から取り除きます。 "バナナ" の位置のインデックスと共に、取り除く項目の総数を指定します。

js
const fruits = ["りんご", "バナナ", "いちご", "マンゴー"];
const start = 1;
const deleteCount = 2;
const removedItems = fruits.splice(start, deleteCount);
console.log(fruits);
// ["りんご", "マンゴー"]
console.log(removedItems);
// ["バナナ", "いちご"]

配列の複数の項目を置換

この例では splice() メソッドを使用して、配列 fruits 内の 2 つの項目を置き換えます。

js
const fruits = ["りんご", "バナナ", "いちご"];
const start = -2;
const deleteCount = 2;
const removedItems = fruits.splice(
  start,
  deleteCount,
  "マンゴー",
  "さくらんぼ",
);
console.log(fruits);
// ["りんご", "マンゴー", "さくらんぼ"]
console.log(removedItems);
// ["バナナ", "いちご"]

配列の走査

この例では for...of ループを使用して配列 fruits を走査し、それぞれの項目をコンソールへログ出力します。

js
const fruits = ["りんご", "マンゴー", "さくらんぼ"];
for (const fruit of fruits) {
  console.log(fruit);
}
// りんご
// マンゴー
// さくらんぼ

ただし for...of は配列を走査する数々の方法の一つにすぎません。他の方法はループと反復処理を参照したり、 every(), filter(), flatMap(), map(), reduce(), reduceRight() の各メソッドのドキュメントを参照したり、また forEach() メソッドを使用している次の例を参照したりしてください。

配列のそれぞれの要素に対して関数を呼び出す

この例では forEach() メソッドを使用して、配列 fruits のそれぞれの要素に対して関数を呼び出しています。この関数ではそれぞれの項目を、その項目のインデックスの番号と共にコンソールへログ出力します。

js
const fruits = ["りんご", "マンゴー", "さくらんぼ"];
fruits.forEach((item, index, array) => {
  console.log(item, index);
});
// りんご 0
// マンゴー 1
// さくらんぼ 2

複数の配列を結合

この例では concat() メソッドを使用して、配列 fruits を配列 moreFruits と結合子、新しい配列 combinedFruits を生成します。 fruitsmoreFruits は変更されないことに注意してください。

js
const fruits = ["りんご", "バナナ", "いちご"];
const moreFruits = ["マンゴー", "さくらんぼ"];
const combinedFruits = fruits.concat(moreFruits);
console.log(combinedFruits);
// ["りんご", "バナナ", "いちご", "マンゴー", "さくらんぼ"]

// 配列 'fruits' は変更されないままです。
console.log(fruits);
// ["りんご", "バナナ", "いちご"]

// 配列 'moreFruits' も変更されないままです。
console.log(moreFruits);
// ["マンゴー", "さくらんぼ"]

配列のコピー

この例では、既存の配列 fruits から新しい配列を生成する方法を 3 通り示します。最初のものはスプレッド構文を使用するもので、次は from() メソッドを使用するもの、その次は slice() メソッドを使用するものです。

js
const fruits = ["いちご", "マンゴー"];

// スプレッド構文でコピーを作成します。
const fruitsCopy = [...fruits];
// ["いちご", "マンゴー"]

// from() メソッドでコピーを作成します。
const fruitsCopy2 = Array.from(fruits);
// ["いちご", "マンゴー"]

// slice() メソッドでコピーを作成します。
const fruitsCopy3 = fruits.slice();
// ["いちご", "マンゴー"]

組み込みの配列コピー操作(スプレッド構文, Array.from(), Array.prototype.slice(), Array.prototype.concat())はすべて、シャローコピーを生成します。配列のディープコピーを得る場合は、 JSON.stringify() で配列を JSON 文字列に変換し、 JSON.parse() でその文字列を新しい配列に戻せば、元の配列から完全に独立した新しい配列ができます。

js
const fruitsDeepCopy = JSON.parse(JSON.stringify(fruits));

また、 structuredClone() メソッドを使用してディープコピーを作成することもできます。これは、ソース内の移譲可能オブジェクトを、コピーするのではなく、新しいコピーに移譲できる利点があります。

最後に、既存の配列を新しい変数に代入しても、配列やその要素のコピーは作成されないことを理解することが重要です。つまり、元の配列の名前と新しい変数の名前は、まったく同じオブジェクトの名前に過ぎません(したがって、常に厳密等価であると評価されます)。したがって、元の配列の値や新しい変数の値に何らかの変更を加えると、もう片方も変更されます。

js
const fruits = ["いちご", "マンゴー"];
const fruitsAlias = fruits;
// 'fruits' と 'fruitsAlias' は同じオブジェクトとなり、厳密等価になります。
fruits === fruitsAlias; // true
// 配列 'fruits' を変更すると、 'fruitsAlias' も変化します。
fruits.unshift("りんご", "バナナ");
console.log(fruits);
// ['りんご', 'バナナ', 'いちご', 'マンゴー']
console.log(fruitsAlias);
// ['りんご', 'バナナ', 'いちご', 'マンゴー']

二次元配列の生成

以下では、文字列の二次元配列としてチェス盤を生成しています。最初の動きは 'p'board[6][4] から board[4][4] にコピーすることで行います。古い位置 [6][4] は空白にします。

js
const board = [
  ["R", "N", "B", "Q", "K", "B", "N", "R"],
  ["P", "P", "P", "P", "P", "P", "P", "P"],
  [" ", " ", " ", " ", " ", " ", " ", " "],
  [" ", " ", " ", " ", " ", " ", " ", " "],
  [" ", " ", " ", " ", " ", " ", " ", " "],
  [" ", " ", " ", " ", " ", " ", " ", " "],
  ["p", "p", "p", "p", "p", "p", "p", "p"],
  ["r", "n", "b", "q", "k", "b", "n", "r"],
];

console.log(`${board.join("\n")}\n\n`);

// キングの前のポーンを 2 つ前へ移動
board[4][4] = board[6][4];
board[6][4] = " ";
console.log(board.join("\n"));

出力を示します。

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
p,p,p,p,p,p,p,p
r,n,b,q,k,b,n,r

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , ,p, , ,
 , , , , , , ,
p,p,p,p, ,p,p,p
r,n,b,q,k,b,n,r

配列を使って値のセットを表にする

js
const values = [];
for (let x = 0; x < 10; x++) {
  values.push([2 ** x, 2 * x ** 2]);
}
console.table(values);

結果は次のようになります。

// 最初の列はインデックスです
0  1    0
1  2    2
2  4    8
3  8    18
4  16   32
5  32   50
6  64   72
7  128  98
8  256  128
9  512  162

照合結果を使用して配列を作成

正規表現 (RegExp) と文字列の照合結果から配列を生成することができます。この配列には、プロパティと、一致したものに関する情報を提供する要素を持ちます。このような配列は RegExp.prototype.exec()String.prototype.match() から返されます。

例えば、次のようになります。

js
// 1 文字の d と、続く 1 文字以上の b と、続く 1 文字の d に一致します
// 一致した b およびそれに続く d を記憶します
// 大文字小文字は区別しません

const myRe = /d(b+)(d)/i;
const execResult = myRe.exec("cdbBdbsbz");

console.log(execResult.input); // 'cdbBdbsbz'
console.log(execResult.index); // 1
console.log(execResult); // [ "dbBd", "bB", "d" ]

照合結果についての詳しい情報は、 RegExp.prototype.exec() および String.prototype.match() のページを参照してください。

仕様書

Specification
ECMAScript Language Specification
# sec-array-objects

ブラウザーの互換性

BCD tables only load in the browser

関連情報