はじめに
多くのプログラミング言語では、データ型として「配列」というものを定義できます。配列は複数のデータを格納することができ、データを効率良く操作するための手段となります。配列の使い方を理解することは、プログラミング初学者にとってのスキル向上となります。
この記事では、JavaScriptにおいての配列の基本的な操作に焦点を当て、配列の定義方法や配列内のデータの変更、追加について解説します。配列に関する基本的なメソッドをご紹介しますが、一度に全てを覚える必要はないので気軽に学んでいただけると幸いです。
この記事の対象者
- JavaScript初学者の方
- 配列について学びたい方
- 効率の良い開発を意識したい初学者の方
この記事で学べること
- 配列の基本的な操作方法について
- 配列とループ処理の組み合わせ方について
配列の基本的な操作
ここでは、JavaScriptにおいての配列の基本的な操作方法について解説します。配列の定義方法から配列内のデータの取得・変更方法など、配列を扱うための基本知識について学びましょう。
配列の定義方法
配列は、複数の値を一つの変数に格納するためのデータ構造です。配列を定義する際は「 [] 」を使用し、その中に複数の要素をカンマ区切りで記述します。配列内へ格納するデータは、通常の変数と同様、あらゆるデータ型のものを選択することができます。以下は、配列の一般的な定義方法です。
let fruits = ['リンゴ', 'バナナ', 'オレンジ'];
上記の例は、fruitsという変数に3つの文字列型のデータを持つ配列を格納しています。配列内の各データは0から始まるインデックス番号が割り当てられます。
配列内のデータの数が多い場合は改行を入れると見やすくなります。
let fruits = [
'リンゴ',
'バナナ',
'オレンジ',
'ブドウ',
'パイナップル',
'レモン'
];
配列には必ずデータを格納する必要はなく、空の配列を定義することもできます。
let array = [];
また、配列は異なる型のデータを格納することもできます。
// [文字列型, 数値型, 真偽値型]を格納しています。
let array = ['文字列', 42, true];
配列を定義する際の「 [] 」は配列リテラルといい、一般的には配列リテラルが使用されますが、JavaScriptにおいての配列はArrayオブジェクトというオブジェクト型のデータなので、Array()というコンストラクタ関数を使用することで以下のように定義することもできます。
let fruits = new Array('リンゴ', 'バナナ', 'オレンジ');
配列へのアクセスとデータの変更
配列内のデータへのアクセスは、各データに割り当てられるインデックスを使用して行うことができます。このアクセスを通じて配列内のデータを参照したり、変更を加えることができます。前述のfruits変数に格納した配列を例に見てみましょう。
let fruits = ['リンゴ', 'バナナ', 'オレンジ'];
この場合、「リンゴ」という文字列には「0」というインデックスが割り当てられ、左から順番に連番でインデックス番号が割り当てられます。インデックスを指定してのアクセスは、
変数名[インデックス]
という記述で行うことができます。
console.log(fruits[0]);
// 結果:リンゴ
console.log(fruits[1]);
// 結果:バナナ
console.log(fruits[2]);
// 結果:オレンジ
配列内のデータの変更は、変数の再代入と同じ要領で行います。
fruits[0] = 'ブドウ';
console.log(fruits);
// 結果:['ブドウ', 'バナナ', 'オレンジ']
同じ要領でデータの追加を行うことができます。
fruits[3] = 'パイナップル';
console.log(fruits);
// 結果:['ブドウ', 'バナナ', 'オレンジ', 'パイナップル']
追加する際、インデックスが連番になっていない場合は値がないことを示す「 empty 」が間に格納されます。emptyのデータへアクセスすると「 undefined 」が返ってきます。
let array = [];
array[2] = 'test';
console.log(typeof array[0]);
// 結果:undefined
console.log(typeof array[1]);
// 結果:undefined
console.log(typeof array[2]);
// 結果:string
また、存在しないインデックスへのアクセスもundefinedになります。
let array = [0, 1, 2];
console.log(typeof array[3]); // 結果:undefined
配列のプロパティ
JavaScriptにおいての配列はオブジェクトであり、多くのメソッドやプロパティを持っています。配列のプロパティには、配列の長さを示すlengthプロパティがあります。
let array = [0, 1, 2];
console.log(array.length);
// 結果:3
lengthプロパティの値を直接変更することで配列内の長さを変更することができますが、恐らく一般的な方法ではありません。
let array1 = [0, 1, 2];
array1.length = 2;
console.log(array1);
// 結果:[0, 1]
let array2 = [0, 1, 2];
array2.length = 3;
console.log(array2);
// 結果:[0, 1, 2, empty]
lengthプロパティを使用することで、配列の末尾にデータを追加することもできます。
let array = [0, 1, 2];
// arrayの末尾に3を追加
array[array.length] = 3;
console.log(array);
// 結果:[0, 1, 2, 3]
配列の基本的なメソッド
JavaScriptの配列は、メソッドとして配列を操作するための多くの機能が定義されています。これらを活用することで、効率的に配列を操作することができます。配列を操作するためのメソッドは、大きく分けて「破壊的メソッド」と「非破壊的メソッド」に分類されます。
破壊的メソッド
破壊的メソッドは呼び出し元の配列そのものを変更します。「元の配列を破壊して新しく配列を作り直す」という意味合いで破壊的という表現がされていると考えることができます。以下は代表的な破壊的メソッドの例です。
- push():配列の末尾に新しいデータを追加
- unshift():配列の先頭に新しいデータを追加
- pop():配列の末尾のデータを削除
- shift():配列の先頭のデータを削除
- splice():配列内のデータを入れ替える
これらののメソッドの使い方について目的別に解説します。
データを追加する
push()メソッドやunshift()メソッドを使用することで配列にデータを追加することができます。これらのメソッドは戻り値として「変更後の配列の長さ(lengthプロパティの値)」を返します。
// 配列の末尾に新しいデータを追加
let array1 = [0, 1, 2, 3];
array1.push('new');
// 戻り値:5
console.log(array1);
// 結果:[0, 1, 2, 3, 4, 'new']
// 配列の先頭に新しいデータを追加
let array2 = [0, 1, 2, 3];
array2.unshift('new');
// 戻り値:5
console.log(array2);
// 結果:['new', 0, 1, 2, 3];
データを削除する
pop()メソッドやshift()メソッドを使用することで配列内のデータを削除することができます。これらのメソッドは「削除したデータ」を戻り値として返します。配列内のデータを削除するというよりも「配列からデータを切り取る」という表現の方が分かりやすいかもしれません。
// 配列の末尾のデータを削除
let array1 = [0, 1, 2, 3, 'delete'];
array1.pop();
// 戻り値:'delete'
console.log(array1);
// 結果:[0, 1, 2, 3];
// 配列の先頭のデータを削除
let array2 = ['delete', 0, 1, 2, 3];
array2.shift();
// 戻り値:'delete'
console.log(array2);
// 結果:[0, 1, 2, 3]
pop()メソッドやshift()メソッドの戻り値を別の変数に代入することもできます。pop()メソッドで見てみましょう。
let array = [0, 1, 2, 3, 'delete'];
/* pop()メソッドの戻り値を
* popItem変数に代入 */
let popItem = array.pop();
console.log(popItem);
// 結果:delete;
データを入れ替える
splice()メソッドを使用することで、配列内の複数のデータを部分的に入れ替えることができます。splice()メソッドは三つの引数を指定します。第一引数には「入れ替えたいデータのインデックス」、第二引数には「入れ替えたいデータの数」、第三引数には「入れ替えるデータ」を指定します。
let array = [0, 'target1', 'target2', 3];
// 入れ替えたいデータのインデックス
let targetIndex = 1;
// 入れ替えたいデータの数
let targetCount = 2;
// 'target1'と 'target2'を'changed'に入れ替える
array.splice(targetIndex, targetCount, 'changed');
// 戻り値:['target1', 'target2']
console.log(array);
// 結果: [0, 'changed', 3]
この他にも、配列を並び替えるsort()メソッドやreverse()メソッドなどが破壊的メソッドに該当します。破壊的メソッドは「安全に配列を扱えない」というデメリットがあるため、元の配列を変更しても他のプログラムに影響がないかを確認する必要があります。
非破壊的メソッド
非破壊的メソッドは呼び出し元の配列を変更せず、新しい配列を作成してそのコピーを返します。
- concat():他の配列やデータを統合して新しい配列を作成
- slice():部分的なデータを取り出して新しい配列を作成
- filter():条件に合致するデータを取り出して新しい配列を作成
- map():配列の各データに指定した関数を適用し、その結果から新しい配列を作成
上記のメソッドの使い方について簡単に解説します。
非破壊的にデータを追加する
concat()メソッドを使用することで、ある配列を基にデータを追加して新たな配列を定義することができます。concat()メソッドは「異なるデータを統合する」と表現できます。以下はconcat()メソッドの使用例です。
let array1 = [0, 1, 2, 3];
let array2 = [4, 5, 6, 7];
let newArray = array1.concat(array2);
console.log(newArray);
// 結果:[0, 1, 2, 3, 4, 5, 6, 7]
concat()メソッドの引数は配列である必要はありません。カンマ区切りで複数のデータを追加することもできます。
let array = [0, 1, 2, 3];
let newArray = array.concat(4, 5, 6, 7);
console.log(newArray);
// 結果:[0, 1, 2, 3, 4, 5, 6, 7]
concat()メソッドは非破壊的メソッドなのでoriginalArray変数に代入されている配列は変更されません。
let array = [0, 1, 2, 3];
let newArray = array.concat(4, 5, 6, 7);
console.log(array);
// 結果:[0, 1, 2, 3]
このように、concat()メソッドを使用することで非破壊的に配列へデータを追加することができます。
非破壊的にデータを削除する
非破壊的に配列内のデータを削除する方法として、slice()メソッドとfilter()メソッドをご紹介します。
slice()メソッド
slice()メソッドは部分的なデータを取り出して配列を作成します。slice()メソッドは、特定の配列の「第一引数(インデックス)から第二引数(インデックス)までのデータを取得」して新しい配列を返します。slice()メソッドを使用することで、配列から非破壊的にデータを削除することができます。
let array = [0, 1, 2, 3];
// 取得したいデータの範囲を定義
let start = 0;
let end = array.length - 1;
let newArray = array.slice(start, end);
console.log(newArray);
// 結果:[0, 1, 2]
上記は、array変数の末尾のデータ以外を取得してnewArray変数に代入しています。slice()メソッドは特定の配列から任意の範囲を指定して新しい配列を作ることができ、slice()メソッドを使用することで「末尾のデータを削除」や「最初のデータを削除」といったことをシンプルな記述で非破壊的に行うことができます。
filter()メソッド
filter()メソッドは条件に合致するデータだけを取り出して新しい配列を作成します。filter()メソッドを使用することでも、非破壊的にデータを削除することができます。
filter()メソッドの引数には関数を記述し、この関数の戻り値に「新しい配列に格納したいデータの条件」を指定します。
以下はfilter()メソッドを使用して配列の末尾のデータを削除する例です。
let array = [0, 1, 2, 3];
let newArray = array.filter(function(value) {
// newArrayに格納するデータの条件を記述
return value !== array.length - 1;
});
console.log(newArray);
// 結果:[0, 1, 2]
メソッドの引数に指定する関数を「コールバック関数」といいます。filter()メソッドでは、コールバック関数の引数に任意の引数名を記述し、これを利用することで元の配列の各データにアクセスします。上記の例では「value」と記述していますが、下記のように変更しても問題ありません。
// コールバック関数の引数に「item」を指定
let newArray = array.filter(function(item) {
// 「item」はarrayの各データです
return item !== array.length - 1;
});
ちなみに、filter()メソッドを使用せずに、for文と条件分岐で非破壊的に配列の末尾のデータを削除する場合は以下のように記述できます。
let array = [0, 1, 2, 3];
let newArray = [];
for (let i = 0; i < array.length; i++) {
if (i !== array.length - 1) {
newArray[i] = array[i];
}
}
console.log(newArray);
// 結果:[0, 1, 2]
ループ処理内に記述してあるif文の条件とfilter()メソッドのコールバック関数の戻り値に指定してある条件が同じであるところがポイントです。
// 以下はfor文内の条件式です
if (i !== array.length - 1) { … }
// 以下はfilter()メソッドの戻り値です
return item !== array.length - 1;
filter()メソッドは条件を工夫することで配列内のデータを柔軟に絞り込むことができます。for文などを利用しても同様の処理を行うことができますが、filter()メソッドを利用するとコードが簡潔になります。
おまけ:データに変更を加えて新しい配列をつくる
JavaScriptの配列でよく使用されるメソッドとして、map()メソッドについても簡単に触れておきます。map()メソッドは配列の各データに対して指定した関数を適用し、その結果から新しい配列を作成します。
let array = [0, 1, 2, 3];
let newArray = array.map(function(value) {
return value * 2;
});
console.log(newArray);
// 結果:[0, 2, 4, 6]
map()メソッドはコールバック関数を引数にとるため、基本的な構文はfilter()メソッドと似ています。以下では、originalArrayの配列の各データに2を乗算した値をnewArrayに格納しています。
let newArray = originalArray.map(function(value) {
return value * 2;
});
for文でも同じことができますが、map()メソッドを使用した方が簡潔なコードになります。
// for文の場合です
let array = [0, 1, 2, 3];
let newArray = [];
for (let i = 0; i < array.length; i++) {
newArray[i] = array[i] * 2;
}
console.log(newArray);
// 結果:[0, 2, 4, 6]
map()メソッドは便利なので配列のループ処理によく利用されます。
これらのように、非破壊的メソッドは元の配列を破壊しないので安全に配列を扱うことができます。元の配列や非破壊的メソッドでコピーされた配列を再利用することができるため、柔軟にデータを管理することができます。
最後に
この記事では、JavaScriptにおいての配列の基本的な操作に焦点を当て、配列の定義方法や配列内のデータの変更・追加、破壊的メソッド・非破壊的メソッドについて解説しました。
多くのメソッドをご紹介しましたが、一度に全てを覚える必要はありません。配列のメソッドにはこの記事でご紹介したもの以外にも多くのものがあり、基本的には目的に応じて調べながら学んでいきます。ですので、利用頻度が多いメソッドは自然と覚えられるようになります。
filter()メソッドやmap()メソッドは引数にコールバック関数を記述するため少し難しく感じたかもしれません。これらは基本的にループ処理の一種なので、for文の基本を理解していればfilter()メソッドやmap()メソッドを使わなくても求める実装ができるかと思います。これらのメソッドはコードの可読性を高める効果があり広く利用されているので、初学者の方にとっても「知っていおいて損はない」という意味合いでご紹介しました。
プログラミングでは、複雑なデータ構造を表現する際に利用されるものとして、配列以外にも連想配列というものがあり、JavaScriptにおいての連想配列はオブジェクトを指しています。以下の記事ではオブジェクトについて初学者の方向けに解説しているので、興味のある方は参考にしていただけると幸いです。
