JavaScript/配列

出典: フリー教科書『ウィキブックス(Wikibooks)』
ナビゲーションに移動 検索に移動

配列(はいれつ、array)とは、数値や文字列など任意の型の値を順番を持って保持するオブジェクトです。

配列リテラル[編集]

配列リテラル(はいれつリテラル、array literal)は、要素を , で区切り全体を [ ] で囲んで表します。最後の要素の , はあっても構いません。

C言語の配列のように、要素数を予め決め全ての要素の型が同じオブジェクトに型付き配列があります。

アラートのコード例
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
alert( ary[2] ); // C
HTMLに組み込んだ場合
<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<title>テスト</title>
<body>
テスト<br>

  <script>
    const ary = [ 'A', 'B', 'C', 'D', 'E' ];
    
    document.write( ary[2] ); // C
  </script>
</body>
</html>
結果
警告ダイアログボックスがポップアップし C と表示されます。

別のコード例
const ary = [ 'A', 'B', 'C', 'D', 'E' ];
alert( ary[0] ); // A
alert( ary[1] ); // B
alert( ary[2] ); // C
alert( ary[3] ); // D
alert( ary[4] ); // E
alert( ary.length ); // 5

上記の配列の 'A' や 'B' などのように、配列の個々の成分のことを、その配列の要素(ようそ、element)と言います。

また、それぞれの要素にアクセスする際には、配列オブジェクトに続いてインデックスindex、添え字、添字、そえじ)を[ ]で囲みます。インデックスは0から始まる整数です。

書式配列オブジェクト[インデックス]

JavaScriptのインデックスは、(1ではなく)0から始まることに注意してください。(なお、C言語の配列も同様に0番目から数え始める方式です。)

よって、JavaScriptの配列の最後の要素のインデックスは、lengthプロパティで取得できる配列の長さ(要素数)よりも1小さくなります。

さて、JavaScriptでは1つの配列に異なるデータ型のオブジェクトを入れることができます。

const ary = [null, false, true, { a: 0, b: 1 }, 123, 3.14, 5n, [0, 1, 2], undefined];
alert(ary); // ,false,true,[object Object],123,3.14,5,0,1,2,
alert(ary[4]); // 123

alert メソッドや console.log メソッドだけでなく document.write の引数などに配列を使うことも可能です。

<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<title>テスト</title>
<body>
テスト<br>

  <script>
    const ary = [ 'A', 'B', 'C', 'D', 'E' ];
    
    document.write( ary[0] ); // A
  </script>
</body>
</html>
疎な配列

配列の length プロパティを変更したり、大きなインデックスを使って要素の書き換えを行ったらどうなるでしょう。

let ary = [1, 2, 3];

ary.length = 10;
console.log(ary); // "1,2,3,,,,,,,"
console.log(ary[7]); // undefined
ary[6] = 99;
ary[8] = void 0;
ary[100] = "str";
delete ary[1];
ary.forEach((x,i) => console.log(`${i}: ${x}`));
// 0: 1
// 2: 3
// 6: 99
// 8: undefined
// 100: str
  • 3行目: 元々の配列 ary のlength 3 を超える 10 をlengthに代入
  • 4行目: ary を文字列化すると "1,2,3,,,,,,,"
  • 5行目: 拡大された範囲の要素は、 undefined (に見えます、本当?)
  • 6行目: 拡大された範囲の要素に数値を代入
  • 7行目: 拡大された範囲の要素に void 0 を代入(undefinedを得るイディオム)
  • 8行目: 拡大された範囲すら超える遠い位置に文字列を代入
  • 9行目: ary の二番目の要素を delete
  • 10行目: forEach メソッドでそれぞれの要素をインデックスとともに表示すると、削除された2番目の配列要素と代入していない 4,5,7,9..99番目要素は callback 関数の呼び出しそのものが有りません。
    void 0 を代入した8番目の要素は callback 関数が呼び出されています(未代入と削除された要素が undefined に見えるのは表現上の問題です)。

このように初期化されていない要素を持つ配列の要素の事を、疎な配列と言います。数学の疎行列(要素の殆どが 0 な行列)とは異なる概念なので字面に騙されないようにして下さい。


Array[編集]

Arrayオブジェクトのコンストラクタの引数は要素のリスト、もしくは配列の長さです。 Arrayは「アレイ」と読み、「配列」(はいれつ)という意味です。

配列の初期化は、次のようにして行います。

// [ 'A', 'B', 'C', 'D', 'E' ]
const ary = new Array( 'A', 'B', 'C', 'D', 'E' );

または

// [ 'A', 'B', 'C', 'D', 'E' ]
const ary = new Array(5); // [empty × 5]
ary[0] = 'A';
ary[1] = 'B';
ary[2] = 'C';
ary[3] = 'D';
ary[4] = 'E';

スプレッド構文[編集]

スプレッド構文を使うと、次のように書くことが出来ます。

// [ 'A', 'B', 'C', 'D', 'E' ]
const ary = new Array(..."ABCDE");

また、for文を使って、動的に値を代入することもできます。 以下の例では、それぞれ0から4が代入されます(1から5ではないことに注意)。

// [ 0, 1, 2, 3, 4 ]
const ary = new Array();
for (let i = 0; i < 5; i++){
  ary[i] = i;
}

スプレッド構文と Arrray.prototype.map メソッドを組み合わせたトリック

// [ 0, 1, 2, 3, 4 ]
const ary = [...Array(5)].map((_, n) => n)

配列の反復処理[編集]

配列の要素を1つずつ取り出して処理するには、for文 (フォーぶん)を使用します。

// A1, B2, C3, D4, E5 を順番にアラート

const ary = [ 'A1', 'B2', 'C3', 'D4', 'E5' ];

for (let i = 0, len = ary.length; i < len; i++) {
    const element = ary[i];
    alert(element);
}

JavaScriptにかぎらず、プログラミングで繰り返し処理をしたい場合、for文というのを使うことが、よくあります。

JavaScript では、配列はオブジェクトとして扱われるので、 .length などのプロパティを持っています。なお 配列の .length プロパティは、その配列の要素数を数えます。なので、上記コード例の ary.length の中身は数値 5 です。

※ 配列で使用できるプロパティやメソッドについて詳しくは『JavaScript/Array』を参照。Arrayコンストラクタを使わずに配列リテラルで定義しても、これらのプロパティやメソッドを使用可能です。

// A, B, C, D, E を順番にアラート

const ary = [ 'A', 'B', 'C', 'D', 'E' ];

ary.forEach(function(element){
    alert(element);
});

Array.prototype.forEachメソッドとアロー関数を使うとより簡素に書けます。

const ary = [ 'A', 'B', 'C', 'D', 'E' ];

ary.forEach(el => alert(el));

for-in文はオブジェクトのプロパティを順番に取り出す構文であり、配列オブジェクトに使用するとに配列の添字と追加されたプロパティのキーを反復対象にしてしまいます。

const ary = [..."abc"]; // [..."abc"] はスプレッド構文で ["a", "b", "c"] を返します。
ary.m = function(){};

for (const item in ary) {
  console.log(item);
}
/*
0
1
2
m
*/

配列など反復構造の要素を順に反復したい場合は、for-of文を使います。

const ary = [..."abc"];
ary.m = function(){};

for (const item of ary) {
  console.log(item);
}
/*
a
b
c
*/

Array.prototype.reduceメソッド[編集]

配列の中から最大値を探す[編集]

const a = []; //巨大配列を乱数で埋め尽くす
for (let i = 0; i < 999999; i++)
  a[i] = Math.random() * 100;

console.log(a.reduce((a, b) => Math.max(a, b), -Infinity)); //reduceは出来る!

console.log(Math.max(...a)); // エラー! RangeError: Maximum call stack size exceeded

最小値・最大値・合計・総積を一度に求める[編集]

const a = [];
for (let i = 0; i < 100; i++)
  a[i] = Math.random() * 100;

ans = a.reduce(({min, max, sum, infProd}, n) => {
  min = Math.min(min, n);
  max = Math.max(max, n);
  sum += n;
  infProd *= n;
  return {min, max, sum, infProd};
}, {
  min: Infinity,
  max: -Infinity,
  sum: 0,
  infProd: 1,
});
console.log(`最小値 = ${ans.min}
最大値 = ${ans.max}
算術平均 = ${ans.sum/a.length}
幾何平均 = ${Math.pow(ans.infProd, 1/a.length)}
`);

配列の配列[編集]

配列の配列(はいれつのはいれつ、array of arrays)とは、配列を要素に含む配列です。二次元配列ともいいます。将棋盤のような2次元のデータ構造を表すのに用いられます。

const ary = [
    [ 'A', 'B', 'C', 'D', 'E' ],
    [ '0', '1', '2', '3', '4' ],
    [ 'a', 'b', 'c', 'd', 'e' ],
    [ 'V', 'W', 'X', 'Y', 'Z' ],
    [ 'v', 'w', 'x', 'y', 'z' ]
];
alert( ary[0][0] ); // A
alert( ary[1][0] ); // 0
alert( ary[2][2] ); // c
alert( ary[3][2] ); // X
alert( ary[4][4] ); // z

n次元の配列 |n>=2| を一般にn-次元配列n-dimensional array)、多次元配列(たじげんはいれつ、multidimensional array)などとも呼びます。

at()メソッド[編集]

ECMA2022から at() メソッドが追加されましたが、引数を整数に変換するときに値の妥当性をチェックしない仕様なので、整数以外がわたらないことをプログラマが保証する必要があり、自明なリテラルを渡す以外の使い方は避けるべきです[1]

at()の機能は、配列に対して .at(-2) のようにメソッド指定すると、末尾から2番目の値を返す配列の要素参照です([ ]のように左辺値化はできません)。つまり、マイナスのインデックス値を指定すると、末尾から数えた位置にある値を返します。

一方、atメソッドで0以上のインデックスを指定した場合は、通常の配列の数え方と同様に、前から数えた数え方をします。

コード例
let b = [15 ,3 ,7, 41];

console.log(b.at(-2) );
console.log(b.at(0) );

console.log(b.at("foo"));
console.log(b.at(NaN));
console.log(b.at(1.5));

console.log(b["foo"]);
console.log(b[NaN]);
console.log(b[1.5]);
実行結果
7
15
15
15
3
undefined
undefined
undefined
at()の引数に整数以外を与えた時の挙動が異常です。
これは、負のインデックスに対応するために一度引数を整数に強制変換していることが原因です。
”foo” ⇒ 0, NaN ⇒ 0, 1.5 ⇒ 1
この様な挙動をするので、at()を使う場合は、プログラマの責任で整数であることを保証する必要があります。


このページ「JavaScript/配列」は、まだ書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にトークページへどうぞ。
  1. ^ Should it really be Math.trunc(n) || 0 #49