JavaScript 入門

JavaScript 配列のイテレーション

配列の反復処理(イテレーション)は、JavaScriptにおける基本中の基本となるコンセプトであり、配列内のすべての要素を一つずつ効率的に処理することを可能にします。

配列のイテレーション技術をマスターすることで、数値の変換、特定の要素の抽出、あるいは各項目に対する特定の関数の適用など、データに対してさまざまな操作を自由自在に行えるようになります。

本章では、JavaScriptにおける3つの強力な配列メソッド、forEachmap、そして filter について深く掘り下げていきます。これらのメソッドを理解することは、配列を効率的に扱う能力を飛躍的に向上させることに直結します。

1. forEach:各要素に対して関数を実行する

forEach メソッドは、配列内の各要素を走査し、提供された関数を各要素に対して一度ずつ実行する手法です。各項目に対して何らかのアクションを実行したい場合、従来の for ループよりも簡潔で可読性の高い代替案となります。

1.1 基本的な使い方

forEach の基本的なシンタックスは以下の通りです。

array.forEach(function(currentValue, index, array) {
  // 実行したいコード
});
  • currentValue (現在の値): 配列内で現在処理されている要素の値。
  • index (インデックス) [オプション]: 現在処理されている要素のインデックス。
  • array (配列) [オプション]: forEach を呼び出している配列自体。

具体的な例を見てみましょう。

const colors = ['red', 'green', 'blue'];

colors.forEach(function(color) {
  // 各カラーをコンソールに出力
  console.log(color);
});

// 出力:
// red
// green
// blue

この例では、forEach メソッドが colors 配列を走査し、各カラーに対してコンソールに値をプリントしています。ここではアノニマスファンクション(匿名関数)を引数として渡しています。

1.2 アロー関数の使用

ES6 (ECMAScript 2015) 以降では、アロー関数を使用することで、より簡潔な記述が可能です。

const numbers = [1, 2, 3];

// 各数値を2倍にして出力
numbers.forEach(number => console.log(number * 2));

// 出力:
// 2
// 4
// 6

ここでは、アロー関数 number => console.log(number * 2)numbers 配列の各要素を受け取り、その2倍の値をコンソールに出力しています。

1.3 インデックスと配列へのアクセス

forEach のループ内では、現在の要素のインデックスや元の配列自体にアクセスすることも可能です。

const fruits = ['apple', 'banana', 'orange'];

fruits.forEach(function(fruit, index, array) {
  console.log(`インデックス ${index} のフルーツは ${fruit} です`);
  console.log(`元の配列は: ${array}`);
});

// 出力:
// インデックス 0 のフルーツは apple です
// 元の配列は: apple,banana,orange
// インデックス 1 のフルーツは banana です
// 元の配列は: apple,banana,orange
// ...

この例は、コールバック関数内でインデックスと元の配列にアクセスする方法を示しています。便利ではありますが、実際には currentValue ほど頻繁には使用されません。

重要:forEach は新しい配列を返しません。
この点は非常に重要です。forEach は既存の配列の各要素に対して関数を実行するだけであり、新しい配列を作成することはありません。要素を変換して、その結果を含む新しい配列を作成したい場合は、次に説明する map メソッドを使用する必要があります。

2. map:配列要素を変換する

map メソッドは、元の配列の各要素に対して提供された関数を適用し、その結果からなる新しい配列を作成します。元の配列を修正せずに、値を変換したい場合に非常に有用です。

2.1 基本的な使い方

map の基本的なシンタックスは以下の通りです。

const newArray = array.map(function(currentValue, index, array) {
  // 変換後の値をリターンする
  return transformedValue;
});
  • currentValue: 現在処理されている要素の値。
  • index [オプション]: 現在の要素のインデックス。
  • array [オプション]: map を呼び出している配列。
  • transformedValue: 新しい配列に追加される値。この値は必ず関数から return される必要があります。

map を使って配列内の数値を2倍にする例を見てみましょう。

const numbers = [1, 2, 3, 4, 5];

const doubledNumbers = numbers.map(function(number) {
  // 各要素を2倍にして新しい配列に含める
  return number * 2;
});

console.log(doubledNumbers); // 出力: [2, 4, 6, 8, 10]
console.log(numbers);        // 出力: [1, 2, 3, 4, 5] (元の配列は変更されない)

mapnumbers 配列を走査し、各数値を2倍にした結果を含む新しい配列 doubledNumbers を返しています。元の numbers 配列はイミュータブル(不変)に保たれています。

2.2 アロー関数の使用

アロー関数を使うと、さらに記述がシンプルになります。

const numbers = [1, 2, 3, 4, 5];
// 数値を二乗した新しい配列を作成
const squaredNumbers = numbers.map(number => number * number);

console.log(squaredNumbers); // 出力: [1, 4, 9, 16, 25]

2.3 配列内のオブジェクトを変換する

map はオブジェクトの配列を処理する際にも最適です。例えば、ユーザーオブジェクトの配列から、ユーザー名だけを抽出した新しい配列を作成する場合です。

const users = [
  { id: 1, username: 'john_doe', email: '[email protected]' },
  { id: 2, username: 'jane_smith', email: '[email protected]' },
  { id: 3, username: 'peter_jones', email: '[email protected]' }
];

// usernameプロパティだけを抽出
const usernames = users.map(user => user.username);

console.log(usernames); // 出力: ['john_doe', 'jane_smith', 'peter_jones']

ここでは、map メソッドが各オブジェクトから username 属性を取り出し、文字列のみの新しい配列を生成しています。

3. filter:条件に基づいて要素を抽出する

filter メソッドは、元の配列の中から提供された条件を満たす(関数が true を返す)要素だけを抽出して、新しい配列を作成します。特定のデータのサブセットを抽出する際に非常に強力なツールとなります。

3.1 基本的な使い方

filter の基本的なシンタックスは以下の通りです。

const newArray = array.filter(function(currentValue, index, array) {
  // 新しい配列に含める場合は true を、
  // 除外する場合は false をリターンする。
  return condition;
});
  • currentValue: 現在処理されている要素の値。
  • index [オプション]: 現在の要素のインデックス。
  • array [オプション]: filter を呼び出している配列。
  • condition: 結果が true または false になる式。

配列から偶数だけを抽出する例を見てみましょう。

const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.filter(function(number) {
  // 数値が偶数であれば true を返す
  return number % 2 === 0;
});

console.log(evenNumbers); // 出力: [2, 4, 6]
console.log(numbers);     // 出力: [1, 2, 3, 4, 5, 6] (元の配列は変更されない)

この例では、filternumbers 配列を走査し、各数値が偶数かどうか (number % 2 === 0) をチェックしています。条件に合致したものだけが evenNumbers 配列に含まれます。

3.2 アロー関数の使用

アロー関数を用いた簡潔な記述です。

const numbers = [1, 2, 3, 4, 5, 6];
// 奇数だけを抽出
const oddNumbers = numbers.filter(number => number % 2 !== 0);

console.log(oddNumbers); // 出力: [1, 3, 5]

3.3 オブジェクトの配列をフィルタリングする

実務において、オブジェクトの配列に対するフィルタリングは多用されます。例えば、製品リストから在庫があるものだけを抽出する場合です。

const products = [
  { id: 1, name: 'Laptop', price: 1200, inStock: true },
  { id: 2, name: 'Mouse', price: 25, inStock: true },
  { id: 3, name: 'Keyboard', price: 75, inStock: false },
  { id: 4, name: 'Monitor', price: 300, inStock: true }
];

// 在庫がある(inStockがtrue)製品だけをフィルタリング
const inStockProducts = products.filter(product => product.inStock);

console.log(inStockProducts);
// 出力: Keyboard 以外の3つの製品オブジェクトが含まれる配列

3.4 map と filter のチェイン(連結)

mapfilter を連結(メソッドチェーン)させることで、より複雑な処理を一段階で行うことができます。例えば、「在庫がある製品の名前だけを取得し、それを大文字に変換する」という処理です。

const products = [
  { id: 1, name: 'Laptop', price: 1200, inStock: true },
  { id: 2, name: 'Mouse', price: 25, inStock: true },
  { id: 3, name: 'Keyboard', price: 75, inStock: false },
  { id: 4, name: 'Monitor', price: 300, inStock: true }
];

const inStockProductNames = products
  .filter(product => product.inStock)          // 1. 在庫ありを抽出
  .map(product => product.name.toUpperCase()); // 2. 名前を大文字に変換

console.log(inStockProductNames); // 出力: ['LAPTOP', 'MOUSE', 'MONITOR']

まず filter で在庫がある製品だけに絞り込み、次に map でその製品名を取り出して大文字に変換しています。

4. 結論

要点をまとめると以下のようになります。

  • forEach: 配列の各要素に対してアクションを実行する。新しい配列は作成しない。
  • map: 配列の各要素を変換し、その結果からなる新しい配列を作成する。
  • filter: 条件に一致する要素だけを抽出し、それらからなる新しい配列を作成する。

これらのイテレーションメソッドを使いこなすことは、クリーンで効率的な JavaScript プログラミングを実現するために極めて重要です。