ES6のジェネレーター機能

1. 発電機の紹介

宣言: Generator 関数は ES6 によって提供される非同期プログラミング ソリューションです。複数の内部状態をカプセル化するステート マシンとみなすことができます。Generator 関数を実行するとトラバーサー オブジェクトが返されるため、トラバーサー オブジェクト生成関数でもあります。Generator関数も普通の関数ですが、2つの特徴があります。1 つ目は、function キーワードと関数名の間に * があること、2 つ目は、さまざまな内部状態を定義するために関数本体内で yield 式が使用されていることです。

 function* fun() {
            yield "张三"  //状态1
            yield "李四"  //状态2
            return "结束" //状态3
        }
        const obj = fun()
        console.log(obj); //fun {<suspended>}

宣言: 返されるのは、内部状態を指すポインター オブジェクト、つまりトラバーサー オブジェクトです。

2. ジェネレーター機能はセグメントで実行されます

宣言: ジェネレーター関数はセグメントで実行され、yield 式は実行を一時停止するマーカーであり、次のメソッドは実行を再開できます。

   console.log(obj.next()); //{value: '张三', done: false}
        console.log(obj.next()); //{value: '李四', done: false}
        console.log(obj.next()); //{value: '结束', done: true}
        // 第三次调用Generator函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。如果有retrun就执行到retrun
        console.log(obj.next()); //{value: undefined, done: true}

3. 収量式

ステートメント: 関数のフラグを一時停止できる式。next() メソッドが呼び出されたときのみ、内部ポインタはステートメントを指します。これは遅延評価の構文関数とみなすことができます。

  function* fun2(a, b) {
            yield a + b
            return a * 5
        }
        const obj2 = fun2(5, 6)
        console.log(obj2); //fun2 {<suspended>}
        console.log(obj2.next()); //{value: 11, done: false}
        console.log(obj2.next()); //{value: 25, done: true}
        console.log(obj2.return(5)); //{value: 5, done: true}

注: return と yield の違いは、関数内に return ステートメントは 1 つだけです。

4. 特殊なフォーム

 説明: Genrator 関数は yield 式を必要としないため、純粋に遅延実行関数になります。

 function* fun3() {
            console.log("Hello world");
        }
        console.log(fun3().next());
        //Hello world
        //{value: undefined, done: true}

5.イールドエクスプレスの注意点

  1. yield 式は、Generator 関数でのみ使用できます。
  2. yield 式を別の式内で使用する場合は、その式を括弧で囲む必要があります。
 function* fun4() {
            console.log("你好" + (yield 123));
            console.log("你好" + (yield 234));
        }
        const obj4 = fun4()
        console.log(obj4.next()); //{value: 123, done: false}
        console.log(obj4.next()); //{value: 234, done: false}

6. Iteratorインターフェースとの関係

説明: Generator 関数は反復子生成関数であるため、オブジェクトの Symbol.iterator プロパティに Generator を割り当てて、オブジェクトに Iterator インターフェイスを持たせることができます。

  const myIter = {}
        myIter[Symbol.iterator] = function* fun5() {
            yield 1
            yield 2
            return 3
        }
        console.log(...myIter);
        //1 2 

 説明: 結果 3 がない場合は、yield で宣言された式のみが走査されることを意味します。(返されたオブジェクトのdoneプロパティがtrueであるため、for...ofループは中止されます)

7. ジェネレーター関数はトラバーサー関数です

const fun6 = function* () {

        }
        const newFun6 = fun6()
        console.log(newFun6 === newFun6[Symbol.iterator]()); //true

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

説明: 次のメソッドは、yield 式の戻り値として使用されるパラメーターを受け取ることができます。

 function* fun7(x) {
            let a = 4 * (yield (x + 1))
            let b = yield (a / 3)
            return (a + b + x)
        }
        const obj5 = fun7(1)
        console.log(obj5.next()); //{value: 2, done: false}
        console.log(obj5.next()); //{value: NaN, done: false}
        console.log(obj5.next()); //{value: NaN, done: true}
        // 第二次运行next()方法的时候不带参数,导致4*undefined等于NaN

        const obj6 = fun7(2)
        console.log(obj6.next()); //{value: 3, done: false}
        console.log(obj6.next(2)); //{value: 2.6666666666666665, done: false}
        console.log(obj6.next(3)); //{value: 13, done: true}

説明: next メソッドのパラメータは前の yield 式の戻り値を表すため、next メソッドを初めて使用するときはパラメータは必要ありません。v8 エンジンは next() メソッドの最初の使用を直接無視し、next() メソッドの 2 回目の使用のみが開始され、パラメーターは引き続き有効です。

9. for...of ループ

注: for...of ループは、実行時に Genrator 関数によって生成された Iterator オブジェクトを自動的にトラバースできるため、この時点で next() メソッドを呼び出す必要はなくなりました。

     function* fun8() {
            yield 1
            yield 2
            yield 3
            return 4
        }
        for (let i of fun8()) {
            console.log(i);
            //1
            //2
            //3
        }

注: 返されたオブジェクトの Done プロパティが true であるため、戻り値はトラバースされず、for...of ループは終了し、返されたオブジェクトは含まれません。

10.ジェネレーター.プロトタイプ.スロー

説明: Generator 関数によって返されるトラバーサー オブジェクトには、Generator 関数の本体でキャプチャできる throw メソッドを持つことができます。

    const fun9 = function* () {
            try {
                yield
            } catch (error) {
                console.log("内部捕获", error);
            }
        }
        const obj8 = fun9()
        obj8.next()
        try {
            obj8.throw("错误1")
            obj8.throw("错误2")
        } catch (error) {
            console.log("外部捕获", error);
        }
        //内部捕获 错误1
        //外部捕获 错误2

説明: ジェネレーター関数内の catch ステートメントが実行されているため、このエラーは捕捉されず、ジェネレーター関数本体がスローされます。

11.ジェネレーター.プロトタイプ.リターン

説明: Generator 関数によって返される traverser 関数には、指定された値を返して Generator 関数を終了できる return メソッドもあります。

     function* fun10() {
            yield 1
            yield 2
        }
        const obj10 = fun10()
        console.log(obj10.next()); //{value: 1, done: false}
        console.log(obj10.return(10));//{value: 10, done: true}
        console.log(obj10.next()); //{value: undefined, done: true}

12.試してみてください...ついに

説明: try...finally コード ブロックを使用すると、try コード ブロックが実行され、return() メソッドがすぐにfinally コード ブロックに入り、実行後に関数全体が終了します。

  function* fun11() {
            try {
                yield 1
                yield 2
            } finally {
                yield 10
                yield 20
            }
        }
        const obj11 = fun11()
        console.log(obj11.next()); //1
        console.log(obj11.return(10)); //{value: 10, done: false}
        console.log(obj11.next()); //{value: 20, done: false}

13. next()、throw()、return() 共通

説明: 実際、Generator 関数は機能すると実行を再開し、yield 式を別のステートメントに置き換えます。

14. 収量*式

説明: Generator 関数内で別の Generator 関数を実行する問題を解決します。

 function* fun12() {
            yield 2
            yield 3
        }
        function* fun13() {
            yield 4
            yield* fun12()
            yield 5
        }
        //    等价于
        function* fun13() {
            yield 4
            yield 2
            yield 3
            yield 5

        }

15. オブジェクトプロパティのジェネレータ関数

注: オブジェクトのプロパティがジェネレーター関数の場合、次の形式で省略できます。

  const obj12 = {
            *fun14() {

            }
        }

16.ジェネレーター機能の様子

説明: Generator 関数は常にトラバーサーを返すため、これは Generator 関数のインスタンスです。この点を変更するにはcallメソッドやapplyメソッドなどで変更できます。

   function* fun15() {
            this.a = 666
            yield 1

        }
        const obj14 = {
     
        }
        const obj15 = fun15()
        obj15.next()
        console.log(obj15.a); //undefined
        // 改变this
        const obj16 = fun15.call(obj14)
        console.log(obj16.next());//{value: 1, done: false}
        console.log(obj14.a);

注: コンストラクターが呼び出された後、この空のオブジェクトは Generator 関数のインスタンス オブジェクトになります。

おすすめ

転載: blog.csdn.net/m0_62785037/article/details/130779082