ES 6文法(12)Iterator

2881 ワード

Iterable
セット内の各項目を処理するのはよく見られます.JavaScriptは多くの反復集合の方法を提供し、簡単なforからmap()とfilter()に循環する.ローズマリーとジェネレータは、反復の概念をコア言語に直接持ち込んで、for...ofサイクルの挙動をカスタマイズするメカニズムを提供します.
MDNのこの説明が十分に理解されていない場合、次の例を参照しても良い.
let authors = {
	allAuthors: {
    	fiction: ['Agla', 'Skks', 'LP'],
    	scienceFiction: ['Neal', 'Arthru', 'Ribert'],
    	fantasy: ['J.R.Tole', 'J.M.R', 'Terry P.K']
  	},
  	Addres: []
}
このデータ構造はすべての著者を集約し、各著者は創作特性によって分類した.すべての作者のリストを取得したいなら、どうすればいいですか?
for(let author of authors){
	console.log(author ) // Uncaught TypeError: authors is not iterable
}
Iterator
IteratorはES 6においてカスタマイズされたエルゴードを実現するためのインターフェースであり、上記の例によれば、このインターフェースを実現することができる.
authors[Symbol.iterator] = function () {
  let allAuthors = this.allAuthors
  let keys = Reflect.ownKeys(allAuthors)
  let values = []
  return {
    next () {
      if (!values.length) {
        if (keys.length) {
          values = allAuthors[keys[0]]
          keys.shift()
        }
      }
      return {
        done: !values.length,
        value: values.shift()
      }
    }
  }
}
このコードはデータ構造にIteratorインターフェースを配置しています.私たちはfor...ofを使ってコードを巡回できます.
for(let value of authors){
	console.log(`${value}`)
}
ユーザー定義のエルゴードの強さをコードで見ましたが、Iteratorはどう分かりますか?まず、いくつかの概念を理解するには、反復プロトコルとローズマリープロトコルがあります.1.ローズマリープロトコル
属性

next
オブジェクトの参照なし関数を返します.オブジェクトには2つの属性があります.doneとvalue
これは2つの概念です.反復可能なプロトコルとローズマリープロトコルです.通俗的には、次の条件に適合することが要求されます.1.まず、彼はオブジェクト2です.次に、このオブジェクトは無参関数next 3を含みます.最後に、nextはオブジェクトに戻ります.オブジェクトはdoneとvalue属性を含みます.doneは巡回が終了するかどうかを表し、valueは現在巡回している値を返します.
next関数がオブジェクト以外の値(falseやundefinedなど)を返すと、Type Errrorのエラーが表示されます.
2.反復可能プロトコルは、JavaScriptオブジェクトがそれらの反復的挙動を定義またはカスタマイズすることを可能にする反復プロトコルであり、例えば、for...of構造においてどの値が循環され得るか(得る).いくつかの内蔵タイプは、内蔵された反復可能なタイプであり、デフォルトの反復動作があります.例えば、Aray or Mapのように、他のタイプはObjectのようなものではありません.反復可能なオブジェクトになるためには、オブジェクトは@@iterator方法を実現しなければならない.このオブジェクト(またはそのプロトタイプタイプchain上のオブジェクト)はSymbol.iteratorの属性である必要があります.
属性

[Symbol.iterator]
オブジェクトの参照なし関数を返します.
オブジェクトを巡回できるようにすると、反復可能なプロトコルに従います.このプロトコルはオブジェクトがSymbol.iteratorをkeyのキー値ペアとして展開することを要求します.valueは参照関数がないので、この関数が返したオブジェクトはサブコマンダープロトコルに従います.GeneratorはGeneratorに慣れてから、自然に反復可能なプロトコルを満たすことがわかった.上記のコードはGeneratorで実現できます.
authors[Symbol.iterator] = function * () {
  let allAuthors = this.allAuthors
  let keys = Reflect.ownKeys(allAuthors)
  let values = []
  while (1) {
    if (!values.length) {
      if (keys.length) {
        values = allAuthors[keys[0]]
        keys.shift()
        yield values.shift()
      } else {
        return false
      }
    } else {
      yield values.shift()
    }
  }
}
同じシーンで、同じデータ構造で、書き方が確かに違っています.Generatorを利用して、表示する必要がなくなったのはローズマリープロトコルです.(next方法とdone、value属性を含む返却対象です.)