zoukankan      html  css  js  c++  java
  • ES6新特性三: Generator(生成器)函数详解

    本文实例讲述了ES6新特性三: Generator(生成器)函数。分享给大家供大家参考,具体如下:

    1. 简介

    ① 理解:可以把它理解成一个函数的内部状态的遍历器,每调用一次,函数的内部状态发生一次改变。

    ② 写法:

        function* f() {}

    ③ 作用:就是可以完全控制函数的内部状态的变化,依次遍历这些状态。

    ④ 运行过程:当调用Generator函数的时候,该函数并不执行,而是返回一个遍历器(可以理解成暂停执行)。通过调用next()开始执行,遇到yield停止执行,返回一个value属性值为当前yield语句的值,done属性为false的对象,循环调用next(),一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。

    示例:

        function* helloWorldGenerator() {
            yield 'hello';
            yield 'world';
            return 'ending';
        }
        var hw = helloWorldGenerator();//第一次调用该方法不会执行,仅返回一个遍历器。
        var a = hw.next();
        while(!a.done){ //当执行到return 时,a.done=true,终止循环
            console.log(a.value+','+a.done);
            a = hw.next();
        }
        console.log(a.value+','+a.done);

    结果:

        hello,false
        world,false
        ending,true

    2. next() 的参数

    ① 我们要知道是next()返回一个对象,yield语句本身是没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。

        function* f() {
            for(var i=0; true; i++) {
                var reset = yield i;
                console.log(reset); //打印reset,验证yield语句是没有返回值的
                if(reset) { i = -1; }
            }
        }
        var g = f();
        console.log(g.next()) // { value: 0, done: false }
        console.log(g.next())// { value: 1, done: false }
        console.log(g.next(true)) // { value: 0, done: false }

    结果:

        { value: 0, done: false }
        undefined
        { value: 1, done: false }
        true
        { value: 0, done: false }

    通过next方法的参数,就有办法在Generator函数开始运行之后,继续向函数体内部注入值。也就是说,可以在Generator函数运行的不同阶段,从外部向内部注入不同的值,从而调整函数行为。

    ②由于next方法的参数表示上一个yield语句的返回值,所以第一次使用next方法时,不能带有参数。V8引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。

        function* foo(x) {
            var y = 2 * (yield (x + 1));
            var z = yield (y / 3);
            return (x + y + z);
        }
        var it = foo(5);
        console.log(it.next(3))// { value:6, done:false }
        console.log(it.next(12))// { value:8, done:false }
        console.log(it.next(13))// { value:42, done:true }

    3. for-of 遍历generator

    for...of循环可以自动遍历Generator函数,且此时不再需要调用next方法,

    一旦next方法的返回对象的done属性为true,for...of循环就会中止,且不包含该返回对象

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

    4. yield* 语句

    ① 如果yield命令后面跟的是一个遍历器,需要在yield命令后面加上星号,表明它返回的是一个遍历器。这被称为yield*语句。

        let a = (function* () {
            yield 'Hello!';
            yield 'Bye!';
        }());
        let b = (function* () {
            yield 'Greetings!';
            yield* a;
            yield 'Ok, bye.';
        }());
        for(let value of b) {
            console.log(value);
        }

    结果:

        Greetings!
        Hello!
        Bye!
        Ok, bye.

    ② yield命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器。

    function* gen(){
        yield* ["a", "b", "c"];
    }
    gen().next() // { value:"a", done:false }

    遍历嵌套数组:

        function* iterTree(tree) {
            if (Array.isArray(tree)) {
                for(let i=0; i < tree.length; i++) {
                    yield* iterTree(tree[i]);
                }
            } else {
                yield tree;
            }
        }
        const tree = [ 'a', ['b', 'c'], ['d', 'e'] ];
        for(let x of iterTree(tree)) {
            console.log(x);
        }// a b c d e
  • 相关阅读:
    numpy数组中round, around, rint, ceil, floor, modf, trunc, fix
    基于KNN算法实现手写数字识别
    PM2.5预测(李宏毅机器学习hw_1)
    numpy的array和asarray
    iOS socket
    UIScrollView
    ios读取文件
    CGContext绘图
    UINavigationController和UITabBarController合用
    window下svn开机自动启动
  • 原文地址:https://www.cnblogs.com/fqh123/p/10622424.html
Copyright © 2011-2022 走看看