Water Sunlight

軽量プログラミングの文法 - JavaScript/Python

ユーザ用ツール

サイト用ツール


js:iteration_protocols

差分

このページの2つのバージョン間の差分を表示します。

この比較画面にリンクする

両方とも前のリビジョン 前のリビジョン
次のリビジョン
前のリビジョン
js:iteration_protocols [2021/06/14 12:14]
y2sunlight
js:iteration_protocols [2021/07/12 13:38] (現在)
tanaka [ジェネレーター]
行 12: 行 12:
 これらのプロトコルを使って、イテレーターオブジェクト及びジェネレーターオブジェクトが定義されています。 これらのプロトコルを使って、イテレーターオブジェクト及びジェネレーターオブジェクトが定義されています。
  
 +\\
 ===== イテレーター ===== ===== イテレーター =====
  
 +イテレーターとは、コレクション内のオブジェクトを列挙する機能を持ったオブジェクトの事です。ES2015<sup>[[js:top#ECMAScript|*2015]]</sup>で導入された for...of 構文は、このイテレーターを使用した構文糖(Syntax Sugar)です。
 +
 +以下にイテレーターを使わないレトロな for 文と、イテレーターを使用した for 文を比べてみます。
 +
 +<sxh javascript;title:レトロなfor文>
 +let students = ['sato', 'suzuki', 'takahashi'];
 +
 +for(let i = 0; i < students.length; i++) {
 +    console.log(students[i]);
 +}
 +</sxh>
 +
 +<sxh javascript;title:for...of構文>
 +let students = ['sato', 'suzuki', 'takahashi'];
 +
 +for(let student of students) {
 +    console.log(student);
 +}
 +</sxh>
 +
 +また、イテレーターオブジェクトを明示的に使用したコードは次の様になります。
 +
 +<sxh javascript;title:イテレーターを使用した場合>
 +let students = ['sato', 'suzuki', 'takahashi'];
 +
 +// イテレーターオブジェクトの取得
 +let it = students[Symbol.iterator]();
 +
 +let obj = it.next();
 +while(!obj.done()) {
 +    console.log(obj);
 +    obj = it.next();
 +}
 +</sxh>
 +
 +Symbol.iteratorはコレクションからイテレーターを取得する為の特別なキーです。詳しくは[[https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator|こちら]]を参照して下さい。
 +
 +\\
 ===== ジェネレーター ===== ===== ジェネレーター =====
 +
 +ジェネレーターは数列などの列挙可能な値(オブジェクト)を、次々と生成し、''yield'' 命令を使って呼び出し元に返す機構です。JavaScriptではES2015<sup>[[js:top#ECMAScript|*2015]]</sup>から導入され、''function*'' 命令(ジェネレーター関数)を使って使用することができます。
 +
 +以下にジェネレーターの簡単な例を示します。
 +
 +<sxh javascript;title:Example>
 +class Student {
 +    // コンストラクタの定義
 +    constructor(name) {
 +        this.name = name;
 +    }
 +
 +    // メソッドの定義
 +    greeting() {
 +        console.log(`I am ${this.name}.`);
 +    }
 +}
 +
 +function* getStudents() {
 +    yield new Student('Sato');
 +    yield new Student('Suzuki');
 +    yield new Student('Takahashi');
 +}
 +
 +for (let student of getStudents()) {
 +    student.greeting();
 +}
 +</sxh>
 +
 +最初にジェネレーター関数が呼び出されると、コードは実行されずイテレーターオブジェクトが返されます。このオブジェクトのことをジェネレーターと呼びます。その後、呼び出し側でジェネレーターの ''next'' 命令が呼び出されると、ジェネレーター関数は最初の ''yield'' までのコードを実行します。このようにしてジェネレーターの ''next'' 命令が呼び出される度に次々と ''yield'' が実行されます。
 +
 +別の例として、2000年から2100年までの閏年を計算するコードを、以下に示します。
 +
 +<sxh javascript;title:Example>
 +function* genLeapYear(start_year) {
 +    let year = start_year;
 +    while(true) {
 +        if(isLeapYear(year)) {
 +            yield year;
 +        }
 +        year++;
 +    }
 +}
 +
 +function isLeapYear(year) {
 +    return (year % 400 == 0) ||
 +           (year % 100 != 0 && year % 4 == 0);
 +}
 +
 +for (let year of genLeapYear(2000)) {
 +    if(year > 2100) break;
 +    console.log(year);
 +}
 +</sxh>
 +
 +上の例はジェネレーターがなぜ使われるのかを端的に示しています。この例から分かるように、ジェネレーターを使用することにより全ての計算結果が格納された配列を用意する必要がなくなります。また、計算の終了を関数の呼び出し側で行うこともできます。
 +
 +\\
  
js/iteration_protocols.1623640447.txt.gz · 最終更新: 2021/06/14 12:14 by y2sunlight