第1章 JavaScript言語仕様

配列

配列の基本

リスト

数値や文字列など複数の値を並べた構造をリストといいます。リストの書き方はとても簡単で、値をカンマで区切り、その全体をカッコで囲むだけです。たとえば1、2、3の 3 つの値のリストは、以下のように記述します。

[1, 2, 3]

文字列の場合は値をダブルクォーテーションやシングルクオーテーションで囲みます。

["A", "B", "C"]

配列

リストを変数に代入したものを配列と呼びます。

let arr = [1, 2, 3];

配列の値は要素とも呼ばれ、上記では数字の1、2、3が要素にあたります。

配列の書式

配列の作成はリストの代入だけではなく、Array オブジェクトを使った作成方法も用意されています。次の3行はどれも同じ配列を作ります。

let arr = new Array(値0, 値1, ..., 値N);
let arr = Array(値0, 値, ..., 値N);
let arr = [値0, 値1, ..., 値N];

インデックス

配列は要素ごとにインデックスと呼ばれる番号を持っていて、その番号を使って各要素にアクセスすることができます。配列のインデックスは 1 ではなく、 0 から始まるので注意してください。1番目の要素のインデックスは 0 、2番目の要素は 1 になります。要素を参照するには、ブラケット( [] )でインデックスを囲みます。

変数[インデックス]

それでは、インデックスを使って配列の要素を参照してみましょう。

要素の参照
ley list = ["A", "B", "C"];

// list の3番目の要素を表示
console.log( list[2] );

配列のインデックスは0から始まるので、list[2] は3つめの要素 C を参照します。配列の要素に値を代入する際も、この参照方法を使います。

要素への代入
let list = [];
list[0] = "A";
list[1] = "B";

要素に変数や式を指定する

配列の要素には、数値や文字列の代わりに変数を指定することもできます。

要素に変数を指定
let v1 = "A";
let v2 = "B";
let list= [v1, v2];

これは次の文と同じ意味になります。

let list= ["A", "B"];

要素に式を指定することもできます。

要素で式を使う
let v = 10;
let arr = [v, v * 2];

これは次の文と同じ意味になります。

let arr = [10, 20];

配列の要素数

配列の要素数は length プロパティで取得できます。

要素数を取得
let list = ["A", "B", "C"];
console.log( list.length );

3

インデックスは0から始まるので、最後の要素のインデックスは length プロパティの値から 1 を引いた値になります。

最後の要素を参照
let list = ["A", "B", "C"];
console.log( list[list.length - 1] );

C

配列のループ処理

for文を使って配列にアクセス

配列のすべての要素にアクセスするには for 文が便利です。後述の for..in 文などに比べると記述量が多いですが、速度や安全性では一番おすすめです。基本、配列であれば for、オブジェクトであれば for..of という使い分けで良いと思います。

var list = ["A", "B", "C"];
for( var i=0 ; i <= list.length; i++ ){
	console.log(list[i]);
}
A
B
C

for 文の条件式内にある list.length で配列の要素数を指定すると、list の要素数に合わせて for 文が終了するので便利です。

for文以外の方法で配列にアクセス

for 文以外にも、for 系の繰り返し処理でしたら for..in 文、for..of 文、forEach 文などが用意されています。
どれも for 文の代わりとして使うことが可能ですが、違いを理解しておくことが必要です。

for..in

先程の for 文を for..in 文に書き直したものが次の例です。

let list = ["A", "B", "C"];
for( var key in list ){
	console.log( list[key] );
}

変数 key にはインデックスが代入されます。

for..in 文はオブジェクトの要素にアクセスするために用意されており、要素がなくなれば繰り返し処理を自動的に終了してくれます。そのため for よりもシンプルに書くことができます。

ただし、for..in 文はプロトタイプを使って追加されたメソッドも一緒に取得するので、利用する際は注意が必要です。例えば次のように、オブジェクトにメソッドが含まれる場合、for..in 文でループさせるとプロパティと同様にメソッドも取得されます。

let list = { A:1, B:2, C:3 };

// プロトタイプを使ったメソッドの追加
Object.prototype.meth = function() {};
// list の要素にアクセス
for( var key in list ) {
	console.log( key + ":" + list[key] );
}
A:1
B:2
C:3

for..of

先程の for文、for..in 文を for..of 文に書き直したものが次の例です。

var list = ["A", "B", "C"];
for( var val of list ){
	console.log( val );
}
A
B
C

for..in の場合 key にインデックスが代入されましたが、for..of の場合は要素の値が代入されます。そのため、今までのように list[key] で要素の値にアクセスする必要がなくなり、直接 key を出力しています。

for..in、for..of の詳しい使い方は制御構文の章を参照してください。

forEach

Array.forEach の構文は以下になります。

構文
array.forEach( コールバック関数, [オブジェクト] )

forEach文に書き直したものが次の例です。

let list = ["A", "B", "C"];
list.forEach(function( val ){
	console.log( val );
});

配列に値が割り当てられていない要素がある場合、処理されずに飛ばされるので注意ください。

let list = ["A", , "C"];
list.forEach(function( val ){
	console.log( "[" + val + "]" );
});
[A]
[C]

配列のメソッド

Arrayオブジェクトには数多くのプロパティ、メソッドが用意されていますが、ここではよく使うメソッドをいくつか紹介します。

配列をスタックやキューとして使う

スタックは後入れ先出し、キューは先入れ先出しのデータ構造です。Array オブジェクトには、スタックを実装した push()、pop()、キューを実装した shift()、unshift() という4つのメソッドが用意されています。

スタック

スタック(stack)には積み重ねるという意味があります。積み重ねた皿のように、皿を取りたいときは山の一番上から、追加したいときも一番上になります。

配列の要素の一番最後に追加するメソッドが push() 、一番最後から取り出すメソッドが pop() です。このとき、取り出された要素は配列から削除されます。

キュー

キュー(queue)には順番待ちの列の意味があり、先頭に対して操作します。

配列の要素の一番最初に追加するメソッドが unshift()、先頭から取り出すのが shift() です。このとき、取り出された要素は配列から削除されます。

 要素を追加要素を取り除く
先頭にunshiftshift
末尾にpushpop

先頭に追加 - unshift()

unshift() は配列の先頭に要素を追加し、追加後の配列の長さを返します。

let list = ["A", "B", "C"];

// unshift() を使って先頭に要素を追加
console.log( list.unshift( "S" ) );
4

追加後の配列には、先頭に指定した要素が追加されています。

console.log( list );
["S", "A", "B", "C"]

先頭から取り出す - shift()

shift() は配列の先頭の要素を削除し、その要素を返します。

let list = ["A", "B", "C"];
console.log( list.shift() );
A

shift() 後、配列から最初の要素が削除されます。

console.log( list );
["B", "C"]

末尾に追加 - push()

push() は配列の末尾に要素を追加し、追加後の配列の長さを返します。

let list = ["A", "B", "C"];
console.log( list.push( "S" ) );
4

追加後の配列には末尾に追加された要素が入ります。

console.log( list );
["A", "B", "C", "S"]

末尾から取り出す - pop()

pop() は配列の末尾の要素を削除し、その要素を返します。

let list = ["A", "B", "C"];
console.log( list.pop() );
C

pop() 後の配列は最後の要素が削除されます。

console.log( list );
["A", "B"]

配列のメソッドを使った逆引きテクニック

配列の結合 - concat()

concat() は引数に指定した配列を結合し、新しい配列を返します。
もとの2つの配列には影響を及ぼしません。

let list1 = ["A", "B", "C"];
let list2 = ["D", "E", "F"];

// concat() を使って list1 に list2 を結合
let list = list1.concat( list2 );

// 結合結果が代入された list を出力
console.log( list );
["A", "B", "C", "D", "E", "F"]
// list1、list2 は変化なし
console.log( list1 );
console.log( list2 );
["A", "B", "C"]
["D", "E", "F"]

配列の要素を文字列として結合 - join()

join() は配列の要素を文字列に結合します。

let list = ["A", "B", "C"];

// join() を使って配列を文字列に結合
console.log( list.join( "-" ) );
A-B-C

要素の値からインデックスを取得 - indexOf() / lastIndexOf()

indexOf() は引数に指定した値とマッチする要素を探し、最初にマッチした要素のインデックスを返します。

let list = ["A", "B", "C", "A"];

// indexOf() を使って要素を検索
console.log( list.indexOf( "A" ) );
0

lastIndexOf() は indexOf() とほぼ同じですが、複数の要素にマッチした場合、最後にマッチした要素のインデックスを返します。マッチしなかった場合は -1 を返します。

let list = ["A", "B", "C", "A"];

// lastIndexOf() を使って最後にマッチした要素を検索
console.log( list.lastIndexOf( "A" ) );
3

指定した位置に要素を追加 - splice()

splice()は配列の任意の場所に要素を削除、追加できるメソッドです。

構文
splice( インデックス, 削除する数, [追加要素][, ..., 追加要素] );

引数

インデックス
配列に追加、もしくは削除したい要素のインデックスを指定します。値がマイナスの場合、配列の末尾から指定した値を引いた数になります。
削除する数
配列から削除する要素の数を指定します。0 の場合は要素を削除しません。
要素
配列に追加したい要素を指定します。
戻り値
削除した要素の配列を返します。

それでは、splice() を使って、配列の2番目に値を追加してみましょう。

let list = ["A", "B", "C"];

// 要素の2番めに - を追加
list.splice( 1, 0, "-" );

console.log( list );

["A", "-", "B", "C"]

第3引数以降に好きなだけ追加したい要素を指定することができます。

let list = ["A", "B", "C"];

// 要素の2番めに - を複数追加
list.splice( 1, 0, "-", "-", "-" );

console.log( list );

["A", "-", "-", "-", "B", "C"]

要素を削除した場合、削除した要素の配列が返されます。このとき、追加する要素を指定しなければ削除だけが行われます。

let list = ["A", "B", "C"];

// 要素の2番めを削除
console.log( list.splice( 1, 2 ) );

["B", "C"]

配列の一部を取得 - slice()

slice() は第1引数で指定した要素から、第2引数で指定した要素までを返します。元の配列に影響はありません。

構文
slice( 開始インデックス, [終了インデックス] ) 

引数

開始インデックス
取得したい要素の開始位置をインデックスで指定します。マイナスを使って配列の末尾からのオフセットを指定することもできます。-2 は配列の末尾から 2 番目の要素を意味します。
開始インデックスを省略した場合は、0 番目の要素から開始します。
終了インデックス
取得したい要素の終了位置をインデックスで指定します。マイナスを使って配列の末尾からのオフセットを指定することもできます。-2 は配列の末尾から 2 番目の要素を意味します。
開始インデックスを省略した場合は、要素の末尾までとなります。

インデックスを指定して要素を取得してみましょう。

let list = ["A", "B", "C"];
// インデックスの1から2の要素を取得
console.log( list.slice( 1, 2 ) );

["B"]

// インデックスの1から3の要素を取得
console.log( list.slice( 1, 3 ) );

["B", "C"]

// 元の要素に変更ありません
console.log( list );

["A", "B", "C"]

要素のソート - sort()

sort() は配列の要素をソートします。

let list = ["B", "C", "A"];
console.log( list.sort() );

["A", "B", "C"]

要素を逆順にする - reverse()

reverse() は配列の要素を逆順に入れ替えます。

let list = ["A", "B", "C"];
console.log( list.reverse() );

["C", "B", "A"]

配列のコピー

配列を複製しようと単純に配列を変数に代入しても、参照渡しになってしまいます。
要素をコピーしたい場合は slice() を使うと簡単です。

let list	= ["A", "B", "C"];
list2		= list.slice();
console.log( list2 );

要素をランダムに取得

配列の値をランダムに取得したい場合、Math オブジェクトの random() を使います。random() に配列の要素数をかけることで、配列のインデックスの範囲の数字をランダムに取得することができます。

let list	= ["A", "B", "C", "D", "E"];

// 0から4までの数字がランダムに返される
let ret = Math.floor( Math.random() * list.length );

console.log(list[ret]);

最大値、最小値を取得

Math オブジェクトを使って配列の要素の最大値や、最小値が取得できます。

let list	= [100, 10, 50, 25, 0];
console.log( Math.max.apply( null, list ) );

100

console.log( Math.min.apply( null, list ) );

0

全ての要素に対して処理する - map()

map() は配列の要素全てに対し、引数に指定した関数の処理を行ってその結果の配列を返します。元の要素に影響はありません。

let list= [1, 2, 3, 4];
let ret = list.map(function( X ){
   return X * 2;
});

console.log( ret );

[2, 4, 6, 8]

多次元配列

多次元配列とは、配列を要素とした配列のことです。例えば、次のような表であれば2次元配列で表現できます。

Y/X012
0ABC
1DEF
2GHI
let list	=[
	["A", "B", "C"],
	["D", "E", "F"],
	["G", "H", "I"],
];
console.log( list[0] );
console.log( list[1] );
console.log( list[2] );

["A", "B", "C"]
["D", "E", "F"]
["G", "H", "I"]

要素にピンポイントでアクセスしたい場合、次のようにインデックスを2つ指定します。最初のインデックスがY軸、次のインデックスがX軸の位置を指定しています。

console.log( list[1][1] );

E

関連記事