概要
フロントエンド開発において、データの操作は避けて通れない重要なスキルです。中でも「配列」は、複数のデータをまとめて扱うための最も基本的なデータ構造であり、その理解と活用は開発効率に直結します。JavaScriptの配列は、単にデータを格納するだけでなく、豊富なメソッドによって多様な操作を可能にします。本記事では、JavaScriptにおける配列の基本から、よく利用されるメソッド、そして実務で役立つ応用的なテクニックまで、現役フロントエンドエンジニアの視点から詳細に解説します。配列を自在に操ることで、より洗練された、効率的なコードを書くための一歩を踏み出しましょう。
詳細解説
配列の基本
配列は、順序付けられた値のコレクションです。各値は「要素」と呼ばれ、それぞれが「インデックス」と呼ばれる数値で識別されます。JavaScriptの配列は、他の多くのプログラミング言語の配列とは異なり、動的で、異なるデータ型の要素を混在させることができます。
配列の生成
配列を生成するには、主に以下の2つの方法があります。
* **配列リテラル:** `[]` を使用する方法が最も一般的で簡潔です。
const fruits = [“apple”, “banana”, “orange”];
const numbers = [1, 2, 3, 4, 5];
const mixed = [“hello”, 123, true, null];
* **`Array` コンストラクタ:** `new Array()` を使用する方法もありますが、通常は配列リテラルの方が推奨されます。引数に単一の数値を与えた場合、その数値の長さを持つ空の配列が生成される点に注意が必要です。
const emptyArray = new Array(5); // 長さ5の空の配列
const initializedArray = new Array(1, 2, 3); // [1, 2, 3]
要素へのアクセス
配列の要素には、インデックスを指定してアクセスします。インデックスは0から始まります。
const colors = [“red”, “green”, “blue”];
console.log(colors[0]); // “red”
console.log(colors[1]); // “green”
console.log(colors[2]); // “blue”
console.log(colors[3]); // undefined (存在しないインデックスへのアクセス)
配列の長さ
配列の要素数を取得するには、`length` プロパティを使用します。
const programmingLanguages = [“JavaScript”, “Python”, “Ruby”];
console.log(programmingLanguages.length); // 3
配列の操作メソッド
JavaScriptの配列は、データを操作するための強力なメソッドを数多く提供しています。ここでは、特に頻繁に利用されるメソッドをいくつか紹介します。
要素の追加・削除
* **`push()`:** 配列の末尾に1つ以上の要素を追加し、新しい配列の長さを返します。
const animals = [“dog”, “cat”];
animals.push(“bird”);
console.log(animals); // [“dog”, “cat”, “bird”]
* **`pop()`:** 配列の末尾から最後の要素を削除し、その削除された要素を返します。
const numbers = [1, 2, 3, 4];
const lastNumber = numbers.pop();
console.log(numbers); // [1, 2, 3]
console.log(lastNumber); // 4
* **`unshift()`:** 配列の先頭に1つ以上の要素を追加し、新しい配列の長さを返します。
const letters = [“b”, “c”];
letters.unshift(“a”);
console.log(letters); // [“a”, “b”, “c”]
* **`shift()`:** 配列の先頭から最初の要素を削除し、その削除された要素を返します。
const letters = [“a”, “b”, “c”];
const firstLetter = letters.shift();
console.log(letters); // [“b”, “c”]
console.log(firstLetter); // “a”
* **`splice()`:** 配列の要素を削除、置換、または追加します。引数は `(startIndex, deleteCount, item1, item2, …)` の形式です。
const colors = [“red”, “green”, “blue”, “yellow”];
// インデックス1から2つの要素を削除し、”purple”と”orange”を追加
const removedColors = colors.splice(1, 2, “purple”, “orange”);
console.log(colors); // [“red”, “purple”, “orange”, “yellow”]
console.log(removedColors); // [“green”, “blue”]
// インデックス3に”pink”を追加
colors.splice(3, 0, “pink”);
console.log(colors); // [“red”, “purple”, “orange”, “pink”, “yellow”]
配列の結合・分割
* **`concat()`:** 2つ以上の配列を結合して新しい配列を作成します。元の配列は変更されません。
const arr1 = [1, 2];
const arr2 = [3, 4];
const combinedArray = arr1.concat(arr2, [5, 6]);
console.log(combinedArray); // [1, 2, 3, 4, 5, 6]
console.log(arr1); // [1, 2] (変更されない)
* **`slice()`:** 配列の一部を新しい配列として抽出します。元の配列は変更されません。引数は `(startIndex, endIndex)` の形式で、`endIndex` は含まれません。
const numbers = [1, 2, 3, 4, 5];
const slicedArray = numbers.slice(1, 4); // インデックス1から3までを抽出
console.log(slicedArray); // [2, 3, 4]
console.log(numbers); // [1, 2, 3, 4, 5] (変更されない)
// 末尾から要素を抽出することも可能
const lastTwo = numbers.slice(-2);
console.log(lastTwo); // [4, 5]
配列の検索・判定
* **`indexOf()`:** 指定した要素が配列内で最初に見つかったインデックスを返します。見つからなかった場合は `-1` を返します。
const fruits = [“apple”, “banana”, “orange”, “banana”];
console.log(fruits.indexOf(“banana”)); // 1
console.log(fruits.indexOf(“grape”)); // -1
* **`lastIndexOf()`:** 指定した要素が配列内で最後に見つかったインデックスを返します。
const fruits = [“apple”, “banana”, “orange”, “banana”];
console.log(fruits.lastIndexOf(“banana”)); // 3
* **`includes()`:** 指定した要素が配列に含まれているかどうかを `true` または `false` で返します。
const numbers = [1, 2, 3, 4];
console.log(numbers.includes(3)); // true
console.log(numbers.includes(5)); // false
* **`find()`:** 条件を満たす配列の最初の要素を返します。条件を満たす要素がない場合は `undefined` を返します。
const users = [
{ id: 1, name: “Alice” },
{ id: 2, name: “Bob” },
{ id: 3, name: “Charlie” }
];
const userBob = users.find(user => user.name === “Bob”);
console.log(userBob); // { id: 2, name: “Bob” }
* **`findIndex()`:** 条件を満たす配列の最初の要素のインデックスを返します。条件を満たす要素がない場合は `-1` を返します。
const users = [
{ id: 1, name: “Alice” },
{ id: 2, name: “Bob” },
{ id: 3, name: “Charlie” }
];
const bobIndex = users.findIndex(user => user.name === “Bob”);
console.log(bobIndex); // 1
* **`some()`:** 配列のいずれかの要素が条件を満たす場合に `true` を返します。一つでも `true` なら `true` を返します。
const numbers = [1, 2, 3, 4, 5];
const hasEven = numbers.some(num => num % 2 === 0);
console.log(hasEven); // true
* **`every()`:** 配列の全ての要素が条件を満たす場合に `true` を返します。一つでも `false` なら `false` を返します。
const numbers = [2, 4, 6, 8];
const allEven = numbers.every(num => num % 2 === 0);
console.log(allEven); // true
const mixedNumbers = [2, 4, 5, 8];
const allEvenMixed = mixedNumbers.every(num => num % 2 === 0);
console.log(allEvenMixed); // false
配列の変換・整形
* **`map()`:** 配列の各要素に対して関数を適用し、その結果からなる新しい配列を生成します。元の配列は変更されません。
const numbers = [1, 2, 3, 4];
const doubledNumbers = numbers.map(num => num * 2);
console.log(doubledNumbers); // [2, 4, 6, 8]
console.log(numbers); // [1, 2, 3, 4] (変更されない)
const users = [
{ id: 1, name: “Alice” },
{ id: 2, name: “Bob” }
];
const userNames = users.map(user => user.name);
console.log(userNames); // [“Alice”, “Bob”]
* **`filter()`:** 条件を満たす配列の要素のみを抽出した新しい配列を生成します。元の配列は変更されません。
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6]
console.log(numbers); // [1, 2, 3, 4, 5, 6] (変更されない)
const products = [
{ name: “Laptop”, price: 1200 },
{ name: “Mouse”, price: 25 },
{ name: “Keyboard”, price: 75 }
];
const expensiveProducts = products.filter(product => product.price > 100);
console.log(expensiveProducts); // [{ name: “Laptop”, price: 1200 }]
* **`reduce()`:** 配列の各要素に対して、指定した関数を適用し、単一の値に集約します。元の配列は変更されません。
const numbers = [1, 2, 3, 4, 5];
// 合計値を計算
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
console.log(sum); // 15
// オブジェクトの配列から特定のプロパティの合計を計算
const items = [
{ name: “Apple”, quantity: 5 },
{ name: “Banana”, quantity: 10 },
{ name: “Orange”, quantity: 3 }
];
const totalQuantity = items.reduce((sum, item) => sum + item.quantity, 0);
console.log(totalQuantity); // 18
* **`sort()`:** 配列の要素を並べ替えます。デフォルトでは文字列としてソートされます。数値やオブジェクトをソートする場合は、比較関数を渡す必要があります。元の配列は変更されます。
const fruits = [“banana”, “apple”, “orange”];
fruits.sort();
console.log(fruits); // [“apple”, “banana”, “orange”]
const numbers = [5, 2, 8, 1, 4];
// 数値を昇順にソート
numbers.sort((a, b) => a – b);
console.log(numbers); // [1, 2, 4, 5, 8]
// 数値を降順にソート
numbers.sort((a, b) => b – a);
console.log(numbers); // [8, 5, 4, 2, 1]
* **`reverse()`:** 配列の要素の順序を反転させます。元の配列は変更されます。
const numbers = [1, 2, 3, 4];
numbers.reverse();
console.log(numbers); // [4, 3, 2, 1]
* **`join()`:** 配列の全ての要素を文字列として結合します。区切り文字を指定できます。
const fruits = [“apple”, “banana”, “orange”];
console.log(fruits.join()); // “apple,banana,orange”
console.log(fruits.join(” – “)); // “apple – banana – orange”
* **`flat()`:** 指定した深さまでネストされた配列を、新しい一次元の配列に平坦化します。
const nestedArray = [1, [2, [3, 4]], 5];
console.log(nestedArray.flat()); // [1, 2, [3, 4], 5]
console.log(nestedArray.flat(2)); // [1, 2, 3, 4, 5]
console.log(nestedArray.flat(Infinity)); // [1, 2, 3, 4, 5]
イミュータブルな操作とミュータブルな操作
配列のメソッドには、元の配列を変更する「ミュータブル (mutable)」なものと、元の配列を変更せずに新しい配列を返す「イミュータブル (immutable)」なものがあります。
* **ミュータブル:** `push()`, `pop()`, `shift()`, `unshift()`, `splice()`, `sort()`, `reverse()`
* **イミュータブル:** `concat()`, `slice()`, `map()`, `filter()`, `reduce()`, `flat()`
現代的なJavaScript開発、特にReactなどの宣言的UIライブラリを使用する場合、イミュータブルな操作が推奨されます。これは、状態管理を容易にし、予期せぬ副作用を防ぐのに役立ちます。
スプレッド構文 (`…`) と配列
ES6で導入されたスプレッド構文 (`…`) は、配列を扱う上で非常に強力なツールです。
* **配列の展開:** 配列の要素を個別に展開して、新しい配列を作成したり、関数に引数として渡したりできます。
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = […arr1, …arr2, 5, 6];
console.log(combined); // [1, 2, 3, 4, 5, 6]
function sum(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
console.log(sum(…numbers)); // 6
* **配列のコピー:** スプレッド構文を使用すると、浅いコピーを簡単に作成できます。
const originalArray = [1, 2, 3];
const copiedArray = […originalArray];
console.log(copiedArray); // [1, 2, 3]
console.log(originalArray === copiedArray); // false (別々の配列オブジェクト)
* **配列の要素の置換 (イミュータブル):** スプレッド構文と `slice()` を組み合わせることで、特定の要素をイミュータブルに変更した新しい配列を作成できます。
const colors = [“red”, “green”, “blue”];
const updatedColors = [
…colors.slice(0, 1), // “red”
“yellow”, // 新しい色
…colors.slice(2) // “blue”
];
console.log(updatedColors); // [“red”, “yellow”, “blue”]
console.log(colors); // [“red”, “green”, “blue”] (変更されない)

コメント