この記事は編集レビューを必要としています。ぜひご協力ください。
この翻訳は不完全です。英語から この記事を翻訳 してください。
これは Harmony(ECMAScript 6) 提案の一部であり、実験段階の技術です。
この技術の仕様は安定していません。ブラウザ互換性の一覧表を確認してください。またこれらの構文や動作は、仕様変更などにより、新しいバージョンのブラウザでは変更される可能性があるという点に注意してください。
ECMAScript第6版のいずれかに加えて、新しい構文や新しいビルトインではなく、プロトコルです。このプロトコルはいくつかの規則を尊重する任意のオブジェクトによって実装されています。
二つのプロトコルがあります。: iterable protocol iterator protocol.
iterable protocol
iterable プロトコルによって、JavaScriptオブジェクトは、for..of
コンストラクタで値がループしているもの等の反復動作を定義、または、カスタマイズできます。Array
やMap
のように、いくつかのビルトインの型はデフォルトの反復動作を持ちます。一方、(Object
のような)他の型は反復動作を持ちません。
iterableになるために、オブジェクトは@@iteratorメソッドを実装する必要があります。これは、オブジェクト(または、prototype chainオブジェクトの一つ)がSymbol
.iterator
キーのプロパティを持つ必要があります。:
プロパティ | 値 |
---|---|
[Symbol.iterator] |
オブジェクトを返す引数なしの関数。iterator protocolに準拠します。 |
(for..of
ループの始まりのように)オブジェクトが反復される必要があるときはいつでも、@@iterator
メソッドが引数なしで呼ばれます。そして、返されるiteratorは、反復される値を取得するために使用されます。
iterator protocol
iterator プロトコルは、値のシーケンスを生成するための標準的な方法を定義します(有限または無限のいずれか)。
次のセマンティクスでnext()
メソッドを実装するとき、オブジェクトはイテレータです。:
プロパティ | 値 |
---|---|
next |
引き数なしの関数。二つのプロパティを持つオブジェクトを返します。:
|
いくつかのイテレータは次々にイテレート可能です:
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"
反復の例
ビルトインの反復可能オブジェクト
String
、 Array
、 TypedArray
、 Map
、Set
は、すべてのビルトイン反復可能オブジェクトです。というのも、それらすべてのプロトタイプオブジェクトは@@
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 operator、 yield*
、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をご覧ください。