JavaScript进阶(八)generator(生成器)实现

756 阅读2分钟

这是我参与8月更文挑战的第二十九天,活动详情查看:8月更文挑战

JavaScript进阶

JavaScript进阶(二)

JavaScript进阶(三)模块化

JavaScript进阶(四)防抖

JavaScript进阶(五)节流

JavaScript进阶(六)继承

JavaScript进阶(七)call, apply, bind

写在前面,generator对于写react的同学相信是相对熟悉一点。react的中间件,react-saga就充分用到的这个 数据类型。废话少说,Let's go!

Generator 实现

generator(生成器)是ES6标准引入的新的数据类型。generator看上去就像是平常用到的函数,它可以返回多次,和 Promise ⼀样,也可以⽤来异步编程。其借鉴了Python的generator的概念和语法。当然你了解Python的generator,相信这个对你来说肯定是相当简单。

//  * 表示这是⼀个 Generator 函数

// 通过 yield 暂停代码

// 调⽤ next 恢复执⾏

function* test() {

    let add = 1 + 2;

    yield 2;

    yield 3;

}

let b = test();

console.log(b.next()); // > { value: 2, done: false }

console.log(b.next()); // > { value: 3, done: false }

console.log(b.next()); // > { value: undefined, done: true }

从以上代码可以发现,该函数执⾏后拥有了 next 函数,执⾏后返回了⼀个对象。调⽤ next 函数的时候,运行yield前面的代码,输出yield后面的结果,然后暂停的代码,再调用,在暂停,最后执行完所有的yield结束。以下是 Generator 函数的简单实现

// cb 编译过的 test 函数
function generator(cb) {
    return (function () {
        var object = {
            next: 0,
            stop: function () {
            }
        };
        return {
            next: function () {
                var ret = cb(object);
                if (ret === undefined) return {value: undefined, done: true};
                return {
                    value: ret,
                    done: false
                };
            }
        };
    })();
}

// 如果你使⽤ babel 编译后可以发现 test 函数变成了这样
function test() {
    var a;
    return generator(function (_context) {
        while (1) {
            switch ((_context.prev = _context.next)) {
                // 可以发现通过 yield 将代码分割成⼏块
                // 每次执⾏ next 函数就执⾏⼀块代码
                // 并且表明下次需要执⾏哪块代码
                case 0:
                    a = 1 + 2;
                    _context.next = 4;
                    return 2;
                case 4:
                    _context.next = 6;
                    return 3;
                // 执⾏完毕
                case 6:
                case "end":
                    return _context.stop();
            }
        }
    });
}

好,今天就到这里了,明天见。 我是Augus,一个爱瞎搞的软件开发工程师。 END~~~