Iterator オブジェクトは、JavaScript における反復可能な操作を行うための標準的なプロトコルを提供します。配列やマップなどのデータ構造を順番に処理する際に利用されます。

Iteratorオブジェクト

編集

Iteratorオブジェクトは、イテレーター(反復子)として機能し、next() メソッドを使用して値を順次取得します。JavaScript の多くの組み込みオブジェクトは、反復可能なプロトコルに準拠しています。

Iteratorの基本構造
const iterator = {
  next: function() {
    // ロジックを記述
    return { value: ..., done: ... };
  }
};

特徴

編集
  • 値の逐次取得: next() メソッドを呼び出すたびに次の値が返されます。
  • 終了判定: 反復が終了すると done: true が返されます。
  • 反復可能オブジェクトとの互換性: [Symbol.iterator] メソッドを持つオブジェクトは、イテレーターとして利用できます。

使用例

編集

カスタムIterator

編集

独自のイテレーターを作成することで、任意のロジックで反復可能なオブジェクトを作成できます。

function createIterator(array) {
  let index = 0;
  return {
    next: function() {
      if (index < array.length) {
        return { value: array[index++], done: false };
      } else {
        return { value: undefined, done: true };
      }
    }
  };
}

const myIterator = createIterator([1, 2, 3]);
console.log(myIterator.next()); // { value: 1, done: false }
console.log(myIterator.next()); // { value: 2, done: false }
console.log(myIterator.next()); // { value: 3, done: false }
console.log(myIterator.next()); // { value: undefined, done: true }

反復可能オブジェクト

編集

配列や文字列などの組み込みオブジェクトは、イテレーターを実装しています。

const array = [10, 20, 30];
const iterator = array[Symbol.iterator]();

console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

イテレーターとループ

編集

イテレーターは for...of ループと密接に連携して動作します。

const array = ['a', 'b', 'c'];
for (const value of array) {
  console.log(value); // 'a', 'b', 'c'
}

プロパティとメソッド

編集

Symbol.iterator

編集

反復可能オブジェクトには [Symbol.iterator] メソッドが存在し、これが呼び出されるとイテレーターオブジェクトを返します。

const iterable = {
  [Symbol.iterator]: function() {
    let step = 0;
    return {
      next: function() {
        step++;
        if (step <= 3) {
          return { value: step, done: false };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

for (const value of iterable) {
  console.log(value); // 1, 2, 3
}

next()

編集

反復を次の値に進め、オブジェクトを返します。返されるオブジェクトには valuedone プロパティが含まれます。

使用例

編集

カウントダウンの例

編集

カスタムイテレーターを作成してカウントダウンを実装します。

function countdown(from) {
  return {
    [Symbol.iterator]: function() {
      let count = from;
      return {
        next: function() {
          if (count >= 0) {
            return { value: count--, done: false };
          } else {
            return { value: undefined, done: true };
          }
        }
      };
    }
  };
}

for (const value of countdown(5)) {
  console.log(value); // 5, 4, 3, 2, 1, 0
}

注意事項

編集
  • 反復可能オブジェクトを利用する際は、done: true が返されるタイミングに注意が必要です。
  • for...of ループは done: true のときに自動的に終了します。

Iterator Helpers

編集

ES(ECMAScript)の Iterator Helpers は、イテレータや非同期イテレータを操作するための便利なメソッドの集合で、繰り返し処理をより簡単に行えるように設計されています。この提案は ECMAScript に導入された新しい機能(ES2024 など)で、配列やマップのようなイテラブルに対して使える高度な操作を、標準化された方法で提供します。

背景

編集

従来の ECMAScript では、イテレータを操作するために手動でループや for...of を使用する必要がありました。特定の操作(フィルタリング、マッピング、合計の計算など)を行うには、コードが複雑になることがありました。Iterator Helpers は、こうした操作を簡潔に実現するためのメソッドを提供します。

主な特徴

編集

Iterator Helpers は、以下のようなメソッドをイテレータ(Iterator または AsyncIterator)に追加します。

Iterator.prototype.constructor

編集

constructor は、Iteratorオブジェクトのインスタンスを作成するメソッドです。通常、直接呼び出すことはなく、新しいIteratorを生成する際に内部的に使用されます。

書式
Iteratorは抽象クラスであり new 直接インスタンス化されることはなく、コレクションの .valiues() / .entries() メソッドや function*(ジェネレータ)で生成します。
const myIterator = [1, 2, 3].values();

Iterator.prototype.drop

編集

drop メソッドは、指定された数の要素をイテレータからスキップします。

書式
iterator.drop(count)
const iterator = [1, 2, 3, 4, 5].values();
const droppedIterator = iterator.drop(2);
// droppedIterator は [3, 4, 5] を含む

Iterator.prototype.every

編集

every メソッドは、イテレータのすべての要素が指定された条件を満たすかどうかをチェックします。

書式
iterator.every(callbackFn)
const numbers = [2, 4, 6, 8].values();
const allEven = numbers.every(num => num % 2 === 0);
// allEven は true

Iterator.prototype.filter

編集

filter メソッドは、指定された条件に基づいて要素をフィルタリングします。

書式
iterator.filter(callbackFn)
const numbers = [1, 2, 3, 4, 5].values();
const evenNumbers = numbers.filter(num => num % 2 === 0);
// evenNumbers は [2, 4] を含む

Iterator.prototype.find

編集

find メソッドは、指定された条件を最初に満たす要素を返します。

書式
iterator.find(callbackFn)
const numbers = [1, 2, 3, 4, 5].values();
const firstEven = numbers.find(num => num % 2 === 0);
// firstEven は 2

Iterator.prototype.flatMap

編集

flatMap メソッドは、各要素に関数を適用し、結果を平坦化します。

書式
iterator.flatMap(callbackFn)
const words = ['hello', 'world'].values();
const chars = words.flatMap(word => word.split(''));
// chars は ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'] を含む

Iterator.prototype.forEach

編集

forEach メソッドは、イテレータの各要素に対して関数を実行します。

書式
iterator.forEach(callbackFn)
const numbers = [1, 2, 3].values();
numbers.forEach(num => console.log(num));
// 1, 2, 3 を出力

Iterator.prototype.map

編集

map メソッドは、各要素に関数を適用し、新しいイテレータを返します。

書式
iterator.map(callbackFn)
const numbers = [1, 2, 3].values();
const squared = numbers.map(num => num * num);
// squared は [1, 4, 9] を含む

Iterator.prototype.reduce

編集

reduce メソッドは、イテレータの要素を単一の値に畳み込みます。

書式
iterator.reduce(callbackFn, initialValue)
const numbers = [1, 2, 3, 4].values();
const sum = numbers.reduce((acc, num) => acc + num, 0);
// sum は 10

Iterator.prototype.some

編集

some メソッドは、少なくとも1つの要素が指定された条件を満たすかどうかをチェックします。

書式
iterator.some(callbackFn)
const numbers = [1, 2, 3, 4, 5].values();
const hasEven = numbers.some(num => num % 2 === 0);
// hasEven は true

Iterator.prototype.take

編集

take メソッドは、イテレータから指定された数の要素を取得します。

書式
iterator.take(count)
const numbers = [1, 2, 3, 4, 5].values();
const firstThree = numbers.take(3);
// firstThree は [1, 2, 3] を含む

Iterator.prototype.toArray

編集

toArray メソッドは、イテレータの要素を配列に変換します。

書式
iterator.toArray()
const numbers = [1, 2, 3].values();
const array = numbers.toArray();
// array は [1, 2, 3]

注意

編集

これらのメソッドは、ECMAScriptの最新の提案に基づいており、すべての環境でサポートされているわけではありません。実際の使用前に、ブラウザーや実行環境の互換性を確認してください。

非同期イテレータ用ヘルパー

編集

非同期イテレータ(AsyncIterator)に対しても同様のメソッドが提供されます。これにより、非同期データストリームの操作が簡単になります。

例: 非同期イテレータでの map

async function* asyncGen() {
  yield 1;
  yield 2;
  yield 3;
}

const result = asyncGen().map(async x => x * 2);
console.log(await result.toArray()); // [2, 4, 6]

メリット

編集
  1. 簡潔で読みやすいコード: 配列のようなイテラブル操作を、他のデータ構造(イテレータや非同期ストリーム)に対しても統一的に使える。
  2. メモリ効率の向上: 全データをメモリに展開する必要がないため、特に大規模なデータストリームの操作で有効。
  3. 非同期操作の統一: 非同期イテレータの扱いが簡単になる。

使用例: 組み合わせ

編集

これらのヘルパーを組み合わせて高度な処理も可能です。

const iterator = [1, 2, 3, 4, 5].values();
const result = iterator
  .filter(x => x % 2 === 0)
  .map(x => x * 10)
  .take(1);

console.log([...result]); // [20]

状態

編集

Iterator Helpers は、現在の ECMAScript 標準(ES2024 以降)に含まれているか、あるいは最新の JavaScript エンジンで試験的に実装されている可能性があります。使用する際は、対応する環境(ブラウザや Node.js)のバージョンを確認してください。

下位階層のページ

編集