JavaScript 速習チュートリアル

JavaScript の配列

1. コード例

const cars = ["サーブ", "ボルボ", "BMW"];

配列(Array)は、データのコレクションを格納するために設計されたオブジェクトタイプです。
JavaScriptの配列には、以下のような主な特徴があります。

  • 要素(Elements): 配列は、要素と呼ばれる値のリストです。
  • 順序付け(Ordered): 要素はインデックス(添字)に基づいて順序付けられています。
  • ゼロインデックス(Zero indexed): 最初の要素のインデックスは 0、2番目は 1 と続きます。
  • 動的サイズ(Dynamic size): 要素の追加や削除に合わせて、サイズが動的に変化します。
  • 異種混合(Heterogeneous): 数値、文字列、オブジェクト、さらには他の配列など、異なるデータ型の要素を混在させて格納できます。

2. なぜ配列を使うのか?

アイテムのリスト(例:車の名前リスト)がある場合、個別の変数に格納すると以下のようになります。

let car1 = "サーブ";
let car2 = "ボルボ";
let car3 = "BMW";

しかし、これらの車をループ処理して特定の車を探したい場合はどうでしょうか? また、車が3台ではなく300台あったらどうなるでしょう?
その解決策が配列です。

配列は一つの名前の下に多くの値を保持でき、インデックス番号を参照することでそれらの値にアクセスできます。

3. 配列の作成

JavaScriptの配列を作成する最も簡単な方法は、配列リテラル(Array literal)を使用することです。

構文:

const array_name = [item1, item2, ...];

慣習として、配列は const キーワードで宣言するのが一般的です。

3.1 コード例

const cars = ["サーブ", "ボルボ", "BMW"];

スペースや改行は重要ではありません。宣言を複数行に分けることも可能です。

const cars = [
  "サーブ",
  "ボルボ",
  "BMW"
];

また、空の配列を作成し、後から要素を追加することもできます。

const cars = [];
cars[0]= "サーブ";
cars[1]= "ボルボ";
cars[2]= "BMW";

4. new Array() キーワードの使用

以下の例でも配列を作成し、値を代入しています。

const cars = new Array("サーブ", "ボルボ", "BMW");

上記の配列リテラルによる方法と結果は全く同じですが、new Array() を使用する必要はありません。
シンプルさ、可読性、および実行速度の観点から、配列リテラル形式を使用してください。

5. 配列要素へのアクセス

インデックス番号を参照することで、配列の要素にアクセスできます。

const cars = ["サーブ", "ボルボ", "BMW"];
let car = cars[0]; // "サーブ" を取得

       注意: 配列のインデックスは 0 から始まります。[0] が最初の要素、[1] が2番目の要素です。

6. 配列要素の変更

以下のステートメントは、cars の最初の要素の値を変更します。

cars[0] = "オペル";

6.1 コード例

const cars = ["サーブ", "ボルボ", "BMW"];
cars[0] = "オペル";
// cars は ["オペル", "ボルボ", "BMW"] になります

7. 配列から文字列への変換

JavaScriptの toString() メソッドは、配列をカンマ区切りの文字列に変換します。

const fruits = ["バナナ", "オレンジ", "リンゴ", "マンゴー"];
document.getElementById("demo").innerHTML = fruits.toString();

結果:

バナナ,オレンジ,リンゴ,マンゴー

8. 配列全体へのアクセス

JavaScriptでは、配列名を参照することで配列全体にアクセスできます。

const cars = ["サーブ", "ボルボ", "BMW"];
document.getElementById("demo").innerHTML = cars;

9. 配列はオブジェクトである

配列は特別なタイプのオブジェクトです。JavaScriptで typeof 演算子を使用すると、配列に対して "object" を返します。

しかし、JavaScriptの配列は「配列」として記述するのが最も適切です。
配列は数値を使用して要素にアクセスします。

// 配列の場合
const person = ["ジョン", "ドウ", 46];
person[0]; // "ジョン" を返す

通常のオブジェクトは名前(キー)を使用してメンバーにアクセスします。

// オブジェクトの場合
const person = {firstName:"ジョン", lastName:"ドウ", age:46};
person.firstName; // "ジョン" を返す

10. 配列の要素にはオブジェクトも格納可能

JavaScriptの変数はオブジェクトになり得ます。配列も一種のオブジェクトであるため、同じ配列内に異なる型の変数を保持できます。

配列の中にオブジェクトを入れたり、関数を入れたり、他の配列を入れたりすることも可能です。

myArray[0] = Date.now;
myArray[1] = myFunction;
myArray[2] = myCars;

11. 配列のプロパティとメソッド

JavaScript配列の真の強みは、組み込みのプロパティとメソッドにあります。

cars.length   // 要素の数を返す
cars.sort()   // 配列をソートする

12. length プロパティ

length プロパティは、配列の長さ(要素の数)を返します。

const fruits = ["バナナ", "オレンジ", "リンゴ", "マンゴー"];
let length = fruits.length; // 4 を返す

length プロパティの値は、常に「最大のインデックス番号 + 1」になります。

12.1 最初の要素へのアクセス

const fruits = ["バナナ", "オレンジ", "リンゴ", "マンゴー"];
let fruit = fruits[0];

12.2 最後の要素へのアクセス

const fruits = ["バナナ", "オレンジ", "リンゴ", "マンゴー"];
let fruit = fruits[fruits.length - 1];

13. 配列要素のループ

配列をループ処理する方法の一つは、for ループを使用することです。

const fruits = ["バナナ", "オレンジ", "リンゴ", "マンゴー"];
let fLen = fruits.length;

let text = "<ul>";
for (let i = 0; i < fLen; i++) {
  text += "<li>" + fruits[i] + "</li>";
}
text += "</ul>";

また、Array.forEach() 関数を使用することもできます。

const fruits = ["バナナ", "オレンジ", "リンゴ", "マンゴー"];

let text = "<ul>";
fruits.forEach(myFunction);
text += "</ul>";

function myFunction(value) {
  text += "<li>" + value + "</li>";
}

14. 配列要素の追加

配列に新しい要素を追加する最も簡単な方法は、push() メソッドを使用することです。

const fruits = ["バナナ", "オレンジ", "リンゴ"];
fruits.push("レモン");  // fruits に新しい要素(レモン)を追加

length プロパティを使用して新しい要素を追加することもできます。

const fruits = ["バナナ", "オレンジ", "リンゴ"];
fruits[fruits.length] = "レモン";  // 末尾に "レモン" を追加

警告 !
高いインデックス番号を指定して要素を追加すると、配列内に未定義(undefined)の「穴(Holes)」が作成される可能性があります。

const fruits = ["バナナ", "オレンジ", "リンゴ"];
fruits[6] = "レモン";  // インデックス3から5までが空の「穴」になる

15. 連想配列(Associative Arrays)

多くのプログラミング言語は、名前付きインデックス(名前をキーにする配列)を持つ配列をサポートしています。これを連想配列(またはハッシュ)と呼びます。

JavaScriptは、名前付きインデックスを持つ配列をサポートしていません。
JavaScriptにおいて、配列は常に数値インデックスを使用します。

const person = [];
person[0] = "ジョン";
person[1] = "ドウ";
person[2] = 46;
person.length;    // 3 を返す
person[0];        // "ジョン" を返す

警告 !!
名前付きインデックスを使用すると、JavaScriptはその配列をオブジェクトとして再定義します。その後、いくつかの配列メソッドやプロパティ(length など)は正しく機能しなくなります。

const person = [];
person["firstName"] = "ジョン";
person["lastName"] = "ドウ";
person["age"] = 46;
person.length;     // 0 を返す
person[0];         // undefined を返す

16. 配列とオブジェクトの違い

  • JavaScriptの配列は、数値インデックスを使用します。
  • JavaScriptのオブジェクトは、名前付きインデックスを使用します。

配列は数値インデックスを持つ特別な種類のオブジェクトと言えます。

16.1 使い分けの基準

  • 要素名を文字列(テキスト)にしたい場合は、オブジェクトを使用してください。
  • 要素名を数値にしたい場合は、配列を使用してください。

17. JavaScript new Array() の落とし穴

JavaScriptには組み込みの配列コンストラクタ new Array() がありますが、代わりに [] を安全に使用できます。

以下の2つはどちらも空の配列 points を作成します。

const points = new Array();
const points = [];

以下の2つはどちらも6つの数値を含む配列を作成します。

const points = new Array(40, 100, 1, 5, 25, 10);
const points = [40, 100, 1, 5, 25, 10];

しかし、new キーワードは予期しない結果をもたらすことがあります。

// 3つの要素を持つ配列を作成:
const points1 = new Array(40, 100, 1);

// 2つの要素を持つ配列を作成:
const points2 = new Array(40, 100);

// 1つの要素を持つ配列を作成...? いいえ、違います。
const points3 = new Array(40);

17.1 よくある間違い

const points = [40];

これは、以下のコードと同じではありません。

const points = new Array(40);
  • const points = [40]; は、要素 40 を一つだけ持つ配列を作成します。
  • const points = new Array(40); は、40個の未定義(undefined)要素を持つ配列を作成します。

18. 配列を判別する方法

「ある変数が配列かどうかをどうやって知るか?」というのはよくある質問です。
問題は、JavaScriptの typeof 演算子が "object" を返すことです。

const fruits = ["バナナ", "オレンジ", "リンゴ"];
let type = typeof fruits; // "object" を返す

これは、JavaScriptにおいて配列がオブジェクトであるためです。

18.1 解決策 1: Array.isArray()

ECMAScript 5 (2009) では、新しく Array.isArray() メソッドが定義されました。

Array.isArray(fruits); // true を返す

18.2 解決策 2: instanceof 演算子

instanceof 演算子は、オブジェクトが特定のコンストラクタによって作成された場合に true を返します。

const fruits = ["バナナ", "オレンジ", "リンゴ"];
(fruits instanceof Array); // true を返す

19. ネストされた配列とオブジェクト

オブジェクトの値に配列を入れたり、配列の値にオブジェクトを入れたりすることができます。

const myObj = {
  name: "ジョン",
  age: 30,
  cars: [
    {name:"フォード", models:["フィエスタ", "フォーカス", "マスタング"]},
    {name:"BMW", models:["320", "X3", "X5"]},
    {name:"フィアット", models:["500", "パンダ"]}
  ]
}

配列の中の配列にアクセスするには、各配列に対してループ処理(for-inループなど)を使用します。

for (let i in myObj.cars) {
  x += "<h1>" + myObj.cars[i].name + "</h1>";
  for (let j in myObj.cars[i].models) {
    x += myObj.cars[i].models[j];
  }
}