ECMA6 - 在JavaScript中使用生成器函数

时间:2016-01-05 05:25:08

标签: javascript ecmascript-6

我花了几天时间学习了ES6版本中引入的JavaScript函数。

有各种各样的地方发电机被解释,但对我来说似乎太有趣的事实是,据说无处不在

  

生成器函数是一种同步编写异步代码的方法。

我想提出的问题是"为什么有这么多需要引入完全不同的编程策略?"

我理解JS代码的异步特性使得新手难以理解和调试代码,但它是否需要完全改变编码风格?

我可能错了或者没有完全理解其介绍背后的概念,但是对这一切的好奇是迫使我提出这个问题。

2 个答案:

答案 0 :(得分:3)

因为闭包不便于简单迭代;即使语言之前支持相同的模式,简化合理常见任务的语法也是值得的。只是比较:

function chain() {
    var args = Array.from(arguments);
    return function() {
        if (args.length === 0) return undefined; // Or some other sentinel
        var nextval = args[0].shift(); // Destructive to avoid copies or more closure vars
        if (args[0].length === 0) args.shift();
        return nextval;
    };
}
var x;
// a, b and c must be indexable, e.g. Arrays; we can't handle other closures without
// requiring some API specific protocol for generation
for (var nextchain = chain(a, b, c); (x = nextchain()) !== undefined;) {
    // do stuff with current value
}

为:

function* chain() {
    for (var i = 0; i < arguments.length; ++i)
        yield* arguments[i];
}
// a, b and c can be any iterable object; yield* can handle
// strings, Arrays, other generators, etc., all with no special handling
for (var x of chain(a, b, c)) {
    // do stuff with current value
}

当然,代码行的节省并不令人难以置信。它主要只是减少样板和不必要的名称,无需处理简单情况下的闭包,并使用for...of语法,提供迭代任意可迭代事物的通用机制,而不是要求用户显式构造初始闭包并按名称推进它。但如果模式足够普遍,那就足够了。

正如评论中所述,a, b, c必须是Array - 就像基于闭包的方法一样(或者您使用chain的作者强加的不同的基于闭包的方法传递给它的东西的任意要求,Array的特殊情况 - 类似于类似于生成器的闭包)和处理是破坏性的(你需要添加更多的闭包状态或制作副本以使其成为非 - 破坏性,使其更复杂或更慢);对于yield*的基于生成器的方法,不需要特殊情况。这使得发电机可以在没有复杂规格的情他们可以轻松地相互建立。

答案 1 :(得分:1)

场景1(异步):您可​​能听说过编写“非阻塞”javascript的重要性。当我们进行I / O操作时,我们在javascript中使用回调或promise来编写非阻塞的javascript代码。

场景2(同步):在javascript中运行无限循环,例如:node -e&#39; while(true){}&#39;可能会冻结你的电脑

考虑到所有这些,ES6生成器允许我们在函数中间有效地“暂停”执行并在将来的某个时间恢复它(同步异步代码)

用例:想象一下,你需要对一系列无限值做一些事情。在这种情况下,数组不会有用,我们可以使用ES6生成器函数

var iterator = generateRandoms();   //suppose it is a generator function which loops through infinite sequence

//generator functions returns a next function which can be called anytime in your code to get the next value from the sequence

console.log(iterator.next());     // { value: 0.4900301224552095, done: false }
console.log(iterator.next());     // { value: 0.8244022422935814, done: false }

就复杂性而言,它是一种新的语法,但不需要很长时间才能掌握它。

进一步阅读:

  1. http://x-team.com/2015/04/generators-work/
  2. https://msdn.microsoft.com/en-in/library/dn858237(v=vs.94).aspx