Please note, this is a STATIC archive of website developer.mozilla.org from November 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Iteration protocols

この記事は編集レビューを必要としています。ぜひご協力ください

この翻訳は不完全です。英語から この記事を翻訳 してください。

これは Harmony(ECMAScript 6) 提案の一部であり、実験段階の技術です。
この技術の仕様は安定していません。ブラウザ互換性の一覧表を確認してください。またこれらの構文や動作は、仕様変更などにより、新しいバージョンのブラウザでは変更される可能性があるという点に注意してください。

ECMAScript第6版のいずれかに加えて、新しい構文や新しいビルトインではなく、プロトコルです。このプロトコルはいくつかの規則を尊重する任意のオブジェクトによって実装されています。

二つのプロトコルがあります。: iterable protocol iterator protocol.

iterable protocol

iterable プロトコルによって、JavaScriptオブジェクトは、for..ofコンストラクタで値がループしているもの等の反復動作を定義、または、カスタマイズできます。ArrayMapのように、いくつかのビルトインの型はデフォルトの反復動作を持ちます。一方、(Objectのような)他の型は反復動作を持ちません。

iterableになるために、オブジェクトは@@iteratorメソッドを実装する必要があります。これは、オブジェクト(または、prototype chainオブジェクトの一つ)がSymbol.iteratorキーのプロパティを持つ必要があります。:

プロパティ
[Symbol.iterator] オブジェクトを返す引数なしの関数。iterator protocolに準拠します。

(for..ofループの始まりのように)オブジェクトが反復される必要があるときはいつでも、@@iteratorメソッドが引数なしで呼ばれます。そして、返されるiteratorは、反復される値を取得するために使用されます。

iterator protocol

iterator プロトコルは、値のシーケンスを生成するための標準的な方法を定義します(有限または無限のいずれか)。

次のセマンティクスでnext()メソッドを実装するとき、オブジェクトはイテレータです。:

プロパティ
next

引き数なしの関数。二つのプロパティを持つオブジェクトを返します。:

  • done (boolean)
    • イテレータは、反復シーケンスの終わりを超えている場合、true値になります。この場合に、valueは、任意の方法でイテレータのreturn valueを指定します。戻り値についてはこちらで説明されています。
    • イテレータがシーケンス内の次の値を生成できるとき false値になります。これは、完全にdoneプロパティを指定しないのと同じです。
  • value - イテレータによって返される任意のJavaScript値。donetrueのとき省略されます。

いくつかのイテレータは次々にイテレート可能です:

var someArray = [1, 5, 7];
var someArrayEntries = someArray.entries();

someArrayEntries.toString();           // "[object Array Iterator]"
someArrayEntries === someArrayEntries[Symbol.iterator]();    // true

例: iteration protocolsを使う

A Stringはビルトイン反復可能オブジェクトの例です。:

var someString = "hi";
typeof someString[Symbol.iterator];          // "function"

Stringのデフォルトイテレータは一つづつStringの文字を返します。:

var iterator = someString[Symbol.iterator]();
iterator + "";                               // "[object String Iterator]"
 
iterator.next();                             // { value: "h", done: false }
iterator.next();                             // { value: "i", done: false }
iterator.next();                             // { value: undefined, done: true }

spread operatorのように、いくつかのビルトインコンストラクタは、hoodの下で同じ反復プロトコルを使用します。:

[...someString]                              // ["h", "i"]

自身の@@iteratorを供給することによって反復動作を再定義できます。:

var someString = new String("hi");          // need to construct a String object explicitly to avoid auto-boxing

someString[Symbol.iterator] = function() {
  return { // this is the iterator object, returning a single element, the string "bye"
    next: function() {
      if (this._first) {
        this._first = false;
        return { value: "bye", done: false };
      } else {
        return { done: true };
      }
    },
    _first: true
  };
};

@@iteratorを再定義することによって、ビルトインコンストラクタの動作にどれほど影響を与えるか注意してください。iteration protocolを使用してください。:

[...someString];                              // ["bye"]
someString + "";                              // "hi"

反復の例

ビルトインの反復可能オブジェクト

StringArrayTypedArrayMapSetは、すべてのビルトイン反復可能オブジェクトです。というのも、それらすべてのプロトタイプオブジェクトは@@iteratorメソッドをもつからです。

ユーザ定義反復可能オブジェクト

下記のように反復可能オブジェクトを生成できます。:

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
[...myIterable]; // [1, 2, 3]

反復可能オブジェクトを受け入れる組み込みAPI

反復可能オブジェクトを受け入れる多くのAPIがあります。例えば: Map([iterable])WeakMap([iterable])Set([iterable])WeakSet([iterable]):

var myObj = {};
new Map([[1,"a"],[2,"b"],[3,"c"]]).get(2);               // "b"
new WeakMap([[{},"a"],[myObj,"b"],[{},"c"]]).get(myObj); // "b"
new Set([1, 2, 3]).has(3);                               // true
new Set("123").has("2");                                 // true
new WeakSet(function*() {
    yield {};
    yield myObj;
    yield {};
}()).has(myObj);                                         // true

他には、Promise.all(iterable)Promise.race(iterable)Array.from()があります。

反復可能オブジェクトを期待する構文

いくつかのステートメントや式は反復可能オブジェクトを期待しています。例えば、for-of ループ、spread operatoryield*destructuring assignment

for(let value of ["a", "b", "c"]){
    console.log(value);
}
// "a"
// "b"
// "c"

[..."abc"]; // ["a", "b", "c"]

function* gen(){
  yield* ["a", "b", "c"];
}

gen().next(); // { value:"a", done:false }

[a, b, c] = new Set(["a", "b", "c"]);
a // "a"

非整形反復可能オブジェクト

反復可能オブジェクトの@@iterator メソッドが反復オブジェクトを返さない場合、その反復可能オブジェクトは非整形反復可能オブジェクトです。それは、ランタイム例外やバグの挙動をもたらす可能性があります。:

var nonWellFormedIterable = {}
nonWellFormedIterable[Symbol.iterator] = () => 1
[...nonWellFormedIterable] // TypeError: [] is not a function

イテレータの例

簡単なイテレータ

function makeIterator(array){
    var nextIndex = 0;
    
    return {
       next: function(){
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
}

var it = makeIterator(['yo', 'ya']);

console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done);  // true

無限のイテレータ

function idMaker(){
    var index = 0;
    
    return {
       next: function(){
           return {value: index++, done: false};
       }
    };
}

var it = idMaker();

console.log(it.next().value); // '0'
console.log(it.next().value); // '1'
console.log(it.next().value); // '2'
// ...

ジェネレータとともに

function* makeSimpleGenerator(array){
    var nextIndex = 0;
    
    while(nextIndex < array.length){
        yield array[nextIndex++];
    }
}

var gen = makeSimpleGenerator(['yo', 'ya']);

console.log(gen.next().value); // 'yo'
console.log(gen.next().value); // 'ya'
console.log(gen.next().done);  // true



function* idMaker(){
    var index = 0;
    while(true)
        yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // '0'
console.log(gen.next().value); // '1'
console.log(gen.next().value); // '2'
// ...

ジェネレータは、イテレータまたは反復可能なオブジェクトですか?

generator objectは、イテレータであり、反復可能オブジェクトです。:

var aGeneratorObject = function*(){
    yield 1;
    yield 2;
    yield 3;
}();
typeof aGeneratorObject.next;
// "function", because it has a next method, so it's an iterator
typeof aGeneratorObject[Symbol.iterator];
// "function", because it has an @@iterator method, so it's an iterable
aGeneratorObject[Symbol.iterator]() === aGeneratorObject;
// true, because its @@iterator method return its self (an iterator), so it's an well-formed iterable
[...aGeneratorObject];
// [1, 2, 3]

仕様

仕様 ステータス コメント
ECMAScript 6 (ECMA-262)
The definition of 'Iteration' in that specification.
勧告候補 初期定義。

関連情報

ES6ジェネレータの詳細について、the function*() documentationをご覧ください。

ドキュメントのタグと貢献者

 このページの貢献者: shide55
 最終更新者: shide55,