ES6:ジェネレーターの詳細

ES6:ジェネレーターの詳細

概要

  • ジェネレーター関数は、ES6が提供する非同期プログラミングソリューションです。これは、複数の内部状態をカプセル化するステートマシンとして理解できます。-

  • Generator関数を実行すると、トラバーサーオブジェクトが返されます。トラバーサーオブジェクトは、関数内の各状態を順番にトラバースできます。

  • ジェネレーター機能には2つの特徴があります。

    • 関数と関数名の間にはアスタリスクがあります。
    • さまざまな内部状態を定義するために、yieldステートメントが関数本体内で使用されます。
  • 例:

    function*helloWorldGenerator(){
          
          
        yield '听不见!';
        yield '重来!';
        return '很有精神!'
    }
    let hw = helloWorldGenerator();
    
    hw.next();	// { value : '听不见!',done : false }
    hw.next();	// { value : '重来!',done : false }
    hw.next();	// { value : '很有精神!',done : true }
    hw.next();	// { value : undefined , done : true }
    
  • この機能を使用すると、関数の非同期プログラミングメカニズムを実現できます。

降伏式

  • トラバーサーの次のメソッドの実行メカニズムは次のとおりです。

    1. yieldステートメントが発生すると、次の操作の実行が一時停止され、yield式の値が返されたオブジェクトのvalue属性値として返されます。
    2. 次回、次のyieldステートメントが検出されるまで、実行を継続するために次の呼び出しが呼び出されたとき。
    3. 歩留まりがない場合は、returnステートメントに直接実行します。
    4. returnステートメントがない場合、値が未定義のオブジェクトが返されます。
  • 利回りは、使用する前にジェネレーター関数に配置する必要があります。

  • 別の式でyieldを使用する場合は、括弧を追加する必要があります。

    console.log('hello' + yield 123); ///error
    console.log('hello' + (yield 123));  //ok 
    

次のメソッドのパラメーター

  • 次のメソッドは、前のステートメントの戻り値として使用されるパラメーターを受け取ることができます。nextにパラメーターがない場合、undefinedを返します。

    function* f(){
          
          
        for(let i=0;ture;i++){
          
          
            let reset = yield i;
            if(reset){
          
          
                i = -1;
            }
        }
    }
    
    let g = f();
    g.next()	//{value : 0,done : false};
    g.next()	//{value : 1,done : false};
    g.next(true)	//{value : 0,done : false};
    

for ... ofメソッド

  • for ... ofループは、Generator関数によって生成されたIteratorオブジェクトを自動的にトラバースできるため、次のメソッドを使用する必要がなくなります。

    function* foo(){
          
          
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
    }
    
    for (let v of foo()){
          
          
        console.log(v);
    }
    

収量*式

  • ジェネレーターで別のジェネレーター関数を呼び出す場合、デフォルトは効果がありません。

    function* foo(){
          
          
        yield 'a';
        yield 'b';
    }
    
    function bar(){
          
          
        yield 1;
        foo();
        yield 2;
    }
    
    for(let i of bar()){
          
          
        console.log(i);
    }
    
    >>1
    >>2
    
  • 直接呼び出しはfor ... of;でfoo()を実行できないことがわかります。

  • このとき、yield *ステートメントを使用する必要があるため、上記のコードは次のように変更できます。

    function* foo(){
          
          
        yield 'a';
        yield 'b';
    }
    
    function bar(){
          
          
        yield 1;
        yield* foo();
        yield 2;
    }
    
    for(let i of bar()){
          
          
        console.log(i);
    }
    
    >>1
    >>'a'
    >>'b'
    >>2
    
  • yield *の後に配列が続く場合、配列のメンバーがトラバースされます。

    function* foo(){
          
          
        yield [1,2,3,4,5];
    }
    foo().next();	//[1,2,3,4,5]
    
    function* foo(){
          
          
        yield* [1,2,3,4,5];
    }
    foo().next();	//{value : 1,done : false}
    
  • yield *式は、ネストされた配列のすべてのメンバーをすばやくトラバースできます。

    function* iterTree(tree){
          
          
        if(Array.isArray(tree)){
          
          
            for(let i=0;i<tree.length;i++);
            yield* iterTree(tree[i]);
        }else{
          
          
            yield tree;
        }
    }
    
    
    const tree = [1,[2,3],[4,5]];
    for(let x of iterTree(tree)){
          
          
        console.log(x);
    }
    
    >> 1
    >> 2
    >> 3
    >> 4
    >> 5
    

これはジェネレーター機能です

  • Generator関数によって返されるイテレータは、元のGenerator関数のインスタンスであり、元の関数のプロトタイプも継承します。

  • したがって、Generator関数のイテレータは、元の関数のプロパティに直接アクセスできません。

    function* foo(){
          
          
        this.a = 1;
    }
    
    let obj = foo();
    console.log(obj.a);			//undefined
    
  • 元の関数のプロパティを取得するには、柔軟なメソッドを使用して取得できます。callメソッドを使用して、これをGenerator関数内にバインドします。

    function* foo(){
          
          
        this.a = 1;
        yield this.b = 2;
        yield this.c = 3;
    }
    let obj = {
          
          };
    let bar = foo.call(obj); 
    
    bar.next();		//{value : 2 , done : false};
    bar.next();		//{value : 3 , done : false};
    
    console.log(obj.a)	// 1
    console.log(obj.b)	// 2
    console.log(obj.c)	// 3
    

おすすめ

転載: blog.csdn.net/yivisir/article/details/108476987