JavaScriptにおける「配列」の正体とは?データ構造の基礎配列の便利なメソッド

データ構造の基礎配列の便利なメソッドのVSCODE画面
目次

JavaScriptにおける「配列」の正体とは?データ構造の基礎を理解する

Webアプリケーション開発において、データは単独で存在することは稀です。「商品一覧」「ユーザーリスト」「ToDoタスク」「1週間の天気予報」など、関連する複数のデータはセットで扱われることがほとんどです。これらを一つ一つの変数(例えば item1, item2, item3…)で管理しようとすると、変数の数が膨大になり、コードの記述量が増えるだけでなく、管理も不可能になります。そこで登場するのが「配列(Array)」です。

配列とは、複数のデータを一つの「箱」に入れて管理するためのデータ構造です。JavaScriptにおける配列は、順序付けられたリスト(Ordered List)として機能します。これは、格納されたデータに「0番目、1番目、2番目…」という順番(インデックス)が割り振られ、その順番通りに並んでいることを意味します。この「順序がある」という性質のおかげで、私たちは「リストの最初のデータを取り出す」「リストの最後に新しいデータを追加する」「順番を並べ替える」といった操作を簡単に行うことができます。

プログラミング言語にはさまざまなデータ型が存在します。JavaScriptには数値(Number)、文字列(String)、真偽値(Boolean)、null、undefinedといった基本的なデータ型がありますが、配列はこれらとは少し異なる「複合的なデータ型」としての側面を持ちます。実はJavaScriptにおいて、配列は「オブジェクト」の一種として扱われます。オブジェクトがキーと値のペアでデータを管理するのに対し、配列はインデックス(数値)と値のペアでデータを管理する特殊なオブジェクトと言えます。

配列の中には、数値や文字列だけでなく、真偽値やオブジェクト、さらには別の配列(多次元配列)まで、あらゆる型のデータを混在させて格納することが可能です。例えば、const data = ["太郎", 25, true]; のように、名前(文字列)、年齢(数値)、会員フラグ(真偽値)を一つの配列に入れることもできます。しかし、実務上は「同じ種類のデータ」をまとめて扱うことが一般的です。

Webブラウザ上で動作するJavaScriptにおいて、配列の重要性は非常に高いです。例えば、ECサイトでカートに入れた商品情報を管理したり、SNSのタイムラインに表示する投稿データをサーバーから取得して一覧表示したりする場合、その裏側では必ず配列が使われています。配列を理解することは、静的なWebページではなく、動的にコンテンツが増減する「Webアプリケーション」を作るための第一歩と言えます。

データの追加メソッドの王道:pushメソッドの仕組みと活用シーン

配列を作成した後、その中身が固定であることは稀です。ユーザーが新しい商品をカートに入れたり、ToDoリストに新しいタスクを追加したりと、アプリケーションの動作に伴ってデータは増えていきます。JavaScriptにおいて、配列の末尾に新しいデータを追加するために最も頻繁に使用されるのが push メソッドです。

push メソッドは、既存の配列の「一番後ろ」に要素を追加します。使い方は非常にシンプルで、配列が入っている変数に対して .push(追加したいデータ) と記述するだけです。

const colors = ["赤", "青"];
colors.push("緑");
console.log(colors); // ["赤", "青", "緑"]

このコードでは、最初に “赤” と “青” という2つの要素を持つ配列を作成しています。その後、push メソッドを使って “緑” を追加しました。結果として、配列の長さ(要素数)は2から3に増え、最後の要素として “緑” が格納されます。

push メソッドの特徴として、一度に複数の要素を追加できる点が挙げられます。colors.push("黄色", "紫"); のように記述すれば、引数に渡した順番通りに配列の末尾に追加されます。これは、APIから取得した複数のデータを一括でリストに追加したい場合などに非常に便利です。

また、push メソッドには「戻り値」が存在します。push を実行すると、要素を追加した後の「新しい配列の長さ(要素数)」が返されます。

const newLength = colors.push("黒");
console.log(newLength); // 4

通常、この戻り値を使うことはあまり多くありませんが、「追加後のデータ件数を知りたい」という場面では役立つ知識です。

ここで一つ注意すべき点があります。それは、push メソッドが「元の配列そのものを変更する(破壊的メソッド)」であるということです。JavaScriptの配列操作メソッドには、元の配列を変更するものと、新しい配列を作成して返すもの(非破壊的メソッド)の2種類があります。push は前者です。Reactなどの一部のフレームワークでは、データの不変性(Immutability)を重視するため、push ではなくスプレッド構文などを使って新しい配列を作る手法が好まれることもありますが、基本的なJavaScriptの操作として push は基本中の基本ですので、必ずマスターしておきましょう。

先頭へのデータ追加:unshiftメソッドとインデックスの再計算

push メソッドが配列の「末尾」にデータを追加するのに対し、配列の「先頭」にデータを追加したい場合に使用するのが unshift メソッドです。例えば、タイムライン表示において最新の投稿を一番上に表示したい場合や、優先度の高いタスクをリストの最上位に割り込ませたい場合などに利用されます。

使い方は push と同様です。

const numbers = [1-3];
numbers.unshift(1);
console.log(numbers); // [1-4]

このコードでは、 という配列の先頭に 1 を追加しています。push と同様に、カンマ区切りで複数の値を渡すことで、一度に複数の要素を先頭に追加することも可能です。戻り値も push と同じく、追加後の新しい配列の長さ(要素数)となります。

しかし、unshift メソッドを使う際には、内部で何が起きているかを理解しておくことが重要です。配列の先頭にデータを追加するということは、もともと「0番目」だった要素が「1番目」に、「1番目」だった要素が「2番目」に…というように、既存のすべての要素のインデックス(部屋番号)が一つずつ後ろにずれることを意味します。

コンピュータの処理として見ると、push は単に末尾にデータを付け足すだけなので高速ですが、unshift は既存のすべてのデータの位置情報を書き換える必要があるため、配列のデータ量が膨大になると処理コストが高くなる傾向があります。数個や数十個程度のデータであれば人間が感じるほどの差はありませんが、大規模なデータを扱う際にはこの「インデックスの再計算」が行われていることを頭の片隅に置いておくと、パフォーマンスを意識したコードが書けるようになります。

初心者のうちは、「末尾に追加なら push」「先頭に追加なら unshift」とセットで覚えておけば問題ありません。どちらも元の配列を書き換える変更操作であることを理解し、用途に合わせて使い分けましょう。

データの削除テクニック:popとshiftで配列の要素を整理する

データの追加方法を学んだら、次は削除方法です。配列から要素を取り除く操作は、追加操作と対(つい)になるメソッドが用意されています。それが pop メソッドと shift メソッドです。

popメソッド:末尾の削除 push の逆を行うのが pop メソッドです。配列の「一番後ろ」の要素を一つ削除します。

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

pop メソッドは引数をとりません。実行すると、配列の最後の要素が削除され、その「削除された要素」が戻り値として返されます。これを利用して、「リストの最後からデータを取り出して処理する」といった使い方が可能です。

shiftメソッド:先頭の削除 unshift の逆を行うのが shift メソッドです。配列の「一番最初(0番目)」の要素を一つ削除します。

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

shift を実行すると、先頭の要素が消えるため、後ろに控えていた要素たちのインデックスが一つずつ前に繰り上がります(1番目が0番目に、2番目が1番目になります)。unshift と同様に、これもインデックスの再計算を伴う処理です。

これらのメソッドも pushunshift と同様に「破壊的メソッド」であり、元の配列の中身を直接変更します。ToDoリストで完了したタスクを消したり、元に戻す(Undo)機能の実装で履歴データの最後を消したりと、削除操作もアプリケーション開発には欠かせません。特定の場所(真ん中など)にある要素を削除したい場合は splice メソッドや filter メソッドを使いますが、まずは基本となる「先頭と末尾の削除」を確実に理解しましょう。

配列操作の基本:ループ処理によるデータへのアクセス方法

配列にデータを格納する最大のメリットは、大量のデータをまとめて処理できる点にあります。配列内のすべてのデータに対して、「画面に表示する」「数値を計算する」「条件判定を行う」といった処理を順番に行うことを「ループ処理(繰り返し処理)」と呼びます。

JavaScriptで最も基本的かつ伝統的なループ処理の方法が for 文です。

const scores = [5-8];
for (let i = 0; i < scores.length; i++) {
    console.log(scores[i]);
}

このコードは、配列 scores の中身を最初から最後まで順番にコンソールに出力します。 for 文の構造は for (初期化; 条件式; 増分処理) となっています。

1. let i = 0: カウンター変数 i を0からスタートさせます(配列のインデックスは0から始まるため)。

2. i < scores.length: 変数 i が配列の要素数(length)より小さい間、処理を続けます。

3. console.log(scores[i]): 配列の i 番目の要素にアクセスして表示します。

4. i++: 処理が一回終わるごとに i を1増やします。

この for 文を使えば、配列に100個データが入っていても、1万個データが入っていても、わずか数行のコードですべてのデータを処理することができます。また、for 文は「逆順にループする」「2つ飛ばしでループする」といった細かい制御も可能です。しかし、単に「配列のすべての要素を順番に使いたい」というだけのケースでは、記述が少し冗長になりがちです。また、ilength の扱いを間違えると、無限ループになったりエラーになったりするリスクもあります。そのため、近年のJavaScript開発では、次項で解説する forEach メソッドなどの「反復メソッド」が好んで使われる傾向にあります。

モダンな配列操作:forEachメソッドとコールバック関数

ES6(ECMAScript 2015)以降のモダンなJavaScript開発において、配列のループ処理を行う際のスタンダードとなっているのが forEach メソッドです。for 文よりも直感的で、記述ミスが起きにくい構文になっています。

forEach メソッドは、配列の各要素に対して、引数として渡した関数(コールバック関数)を一度ずつ実行します。

const members = ["田中", "鈴木", "佐藤"];

members.forEach((name) => {
    console.log(`${name}さん、こんにちは`);
});

このコードでは、members 配列の要素が順番に取り出され、変数 name に代入された状態で、アロー関数 => { ... } の中身が実行されます。 1回目は name が “田中”、2回目は “鈴木”、3回目は “佐藤” となり、それぞれの挨拶が出力されます。

forEach メソッドの利点は、インデックス(i)の管理やループ終了条件(length)を気にする必要がないことです。「配列にあるデータの数だけ繰り返す」という意図がコードから明確に伝わるため、可読性が高くなります。

コールバック関数には、第一引数に「要素の値」、第二引数に「インデックス」、第三引数に「処理中の配列そのもの」を受け取ることができます。

members.forEach((name, index) => {
    console.log(`${index + 1}番目の会員:${name}`);
});

このように記述すれば、通し番号付きでリストを表示することも簡単です。addEventListener でイベント処理を書く際にもコールバック関数を使用しましたが、配列操作においても「関数を引数として渡して処理内容を定義する」というパターンは頻出ですので、慣れておきましょう。

条件に合うデータだけを取り出す:filterメソッドによる検索

Webアプリケーションでは、データの一覧から特定の条件に合うものだけを絞り込んで表示したい場面が多々あります。例えば、「完了していないタスクだけを表示する」「価格が1000円以下の商品だけを探す」といったケースです。このような「検索・フィルタリング」を行うために特化したメソッドが filter です。

filter メソッドは、配列の各要素に対してコールバック関数を実行し、その関数が true を返した要素だけを集めて「新しい配列」を作成します。

const numbers = [1, 9-12];

// 30以上の数字だけを抽出
const highNumbers = numbers.filter((num) => {
    return num >= 30;
});

console.log(highNumbers); // [10-12]

この例では、num >= 30 という条件式が true になる要素だけが highNumbers 配列に残ります。条件に合わない 102 は除外されます。

重要なポイントは、filter メソッドは「非破壊的メソッド」であるという点です。元の配列 numbers は変更されず、フィルタリングされた結果が「新しい配列」として返されます。これにより、元のデータを保持したまま、表示用のデータだけを加工して使うといった安全なデータ操作が可能になります。

また、filter はオブジェクトの配列に対しても威力を発揮します。

const users = [
    { name: "A", active: true },
    { name: "B", active: false },
    { name: "C", active: true }
];

const activeUsers = users.filter(user => user.active);

このように書くだけで、有効(activeがtrue)なユーザーだけのリストを一瞬で作成できます。for 文と if 文を組み合わせて書くよりも圧倒的にシンプルで、バグも入りにくい書き方です。

配列データを加工して新しいリストを作る:mapメソッドの威力

filter が「選別」を行うメソッドだとすれば、map は「加工・変換」を行うメソッドです。配列に入っているすべてのデータに対して何らかの処理を行い、その結果を新しい配列として取得したい場合に使用します。

map メソッドは、forEach と同様に配列の各要素に対して関数を実行しますが、決定的な違いは「戻り値がある」ことです。コールバック関数内で return した値が、新しい配列の要素として蓄積されます。

const prices = [13, 14];

// すべての価格を1.1倍(税込み)にする
const taxPrices = prices.map((price) => {
    return price * 1.1;
});

console.log(taxPrices); // [15]

このコードでは、元の prices 配列の各要素を1.1倍した値を新しい配列 taxPrices に格納しています。元の prices はそのまま残ります。

Web開発の現場、特にReactなどのフレームワークを使用する場合、この map メソッドは頻繁に使用されます。例えば、サーバーから取得したデータ配列を、HTMLのタグ(<li>など)の配列に変換して画面に表示する際などに利用されます。 「配列のデータ構造を別の形に変換したい」と思ったときは、まず map メソッドの利用を検討してみてください。push で空の配列に詰め直すループ処理を書くよりも、ずっとスマートに記述できます。

DOM操作における配列:NodeListと配列の決定的な違い

JavaScriptでWebページの要素を操作する際、document.querySelectorAll() メソッドなどを使って複数の要素を取得することがあります。

const buttons = document.querySelectorAll(".btn");

この buttons に入っているデータは、一見すると配列のように見えます。buttons でアクセスできたり、buttons.length で数を取得できたりします。しかし、これは厳密には配列ではなく「NodeList」と呼ばれるオブジェクト(またはHTMLCollection)です。

NodeListは「配列のようなもの(Array-like Object)」であり、本物の配列ではありません。そのため、ここまで紹介した mapfilterpush といった配列専用の便利なメソッドが使えない場合があります(ブラウザの仕様により forEach はNodeListでも使えることが多いですが、他のメソッドは使えません)。

NodeListに対して map などの配列メソッドを使いたい場合は、NodeListを「本物の配列」に変換する必要があります。最も簡単な方法は「スプレッド構文 [...]」を使うことです。

const buttonsArray = [...buttons];

このように [...] で囲むことで、NodeListの中身を展開して新しい配列を作成できます。もしくは Array.from(buttons) を使う方法もあります。一度配列に変換してしまえば、filter で特定のボタンだけを抽出したり、map でテキストだけを取り出したりと、自由自在に操作できるようになります。DOM操作と配列操作を組み合わせる際は、この「型」の違いに注意しましょう。

実践的なデータ処理:APIから取得したJSONデータの配列操作

最後に、これまでの知識が実際のアプリ開発でどう活かされるかを見てみましょう。現代のWeb開発では、fetch 関数などを使ってサーバー(API)からデータを取得し、それを画面に表示する処理が基本となります。

APIから返ってくるデータ(JSON)の多くは、「オブジェクトが入った配列」の形をしています。 例えば、記事一覧を取得すると以下のようなデータが返ってきます。

[
    { id: 1, title: "記事A", tags: ["JS", "Web"] },
    { id: 2, title: "記事B", tags: ["HTML"] },
    ...
]

開発者はこのデータを fetch で受け取り(非同期処理)、配列として扱います。

1. 検索: filter を使って、特定のタグが含まれる記事だけを絞り込む。

2. 加工: map を使って、データからHTML文字列(<div class="article">...</div>)を作成する。

3. 表示: 絞り込まれ、加工されたデータをDOMに追加して画面に表示する。

このように、Webアプリケーションの「機能」を作るということは、突き詰めれば「配列データの操作」であると言っても過言ではありません。 今回学んだ push による追加、filter による検索、forEachmap による処理は、ToDoリストアプリ、チャットアプリ、ECサイトの商品検索など、あらゆる場面で応用できる基礎技術です。まずは、ブラウザのコンソールで小さな配列を作って、実際にメソッドを動かしながら挙動を確かめてみてください。その積み重ねが、自由にアプリを作る力へと繋がっていきます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次