JavaScript 1.7中提供的一种新机制是yield,对生成器和迭代器很有用。
目前仅在Mozilla浏览器中支持(我知道)。有哪些方法可以在不可用的浏览器中模拟此行为?
答案 0 :(得分:18)
好吧,你总是可以编写一个外部函数来初始化一个闭包中的变量,然后返回一个做你想做的工作的对象。
function fakeGenerator(x) {
var i = 0;
return {
next: function() {
return i < x ? (i += 1) : x;
}
};
}
现在你可以写:
var gen = fakeGenerator(10);
然后反复拨打gen.next()
。在真实生成器上模拟“close()”方法的“最终”行为是很棘手的,但是你可能能够到达某个地方。
答案 1 :(得分:7)
与Pointy的答案类似,但使用hasNext
方法:
MyList.prototype.iterator = function() { //MyList is the class you want to add an iterator to
var index=0;
var thisRef = this;
return {
hasNext: function() {
return index < thisRef._internalList.length;
},
next: function() {
return thisRef._internalList[index++];
}
};
};
hasNext
方法让你循环:
var iter = myList.iterator() //myList is a populated instance of MyList
while (iter.hasNext())
{
var current = iter.next();
//do something with current
}
答案 2 :(得分:4)
对于非平凡的生成器函数,您将需要使用某种工具将代码转换为ES3等效代码,以便它可以在任何现代浏览器中运行。我建议尝试Traceur,它大致可以描述为ES6到ES3源代码转换器。由于生成器是用于ES6的语言功能,因此Traceur将能够为您翻译它们。
Traceur提供demo page,您可以在其中键入ES6代码并查看动态生成的ES3。如果输入的内容很简单:
// Note that this declaration includes an asterisk, as specified by current ES6
// proposals. As of version 16, Firefox's built-in support for generator
// functions does not allow the asterisk.
function* foo() {
var n = 0;
if (n < 10) {
n++;
yield n;
}
}
for (var n of foo()) {
console.log(n);
}
您将看到等效的ES3代码非常重要,并且需要包含traceur.runtime
以便代码在浏览器中正确运行。运行时在http://traceur-compiler.googlecode.com/git/src/runtime/runtime.js中定义,目前为14K(未经分析)。这是一个非常重要的代码量,尽管使用Closure Compiler可以对其进行大量优化。
请注意,还提交了一个错误,提供了从traceur.runtime
命名空间内联所需函数的选项,这样就无需完全包含runtime.js
:https://code.google.com/p/traceur-compiler/issues/detail?id=119。
答案 3 :(得分:2)
没有某种编译器或预处理器......没有。
你最接近的就是这样:
function doStuff() {
var result = { };
function firstStuf() { ...; result.next = secondStuff; return 42; };
function secondStuf() { ...; result.next = thirdStuff; return 16; };
function thirdStuf() { ...; result.next = null; return 7; };
result.next = firstStuff;
return result;
}
但是,嗯......这很糟糕,真的不是替代品。
答案 4 :(得分:2)
我已经开始了一个小项目试图通过一些回调技巧来做到这一点。由于无法在“标准”JavaScript中创建真正的协同程序,因此不会有一些警告,例如:
.next()
之类的东西等),yield
- 因为这是“普通”JavaScript,没有语法限制阻止你这样做) ,好的一面是yield
! :)
来自MDC page的Fibonacci示例如下所示:
var fibonacci = Generator(function () {
var fn1 = 1;
var fn2 = 1;
while (1){
var current = fn2;
fn2 = fn1;
fn1 = fn1 + current;
this.yield(current);
}
});
console.log(fibonacci.take(10).toArray());
输出:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
该项目位于https://bitbucket.org/balpha/lyfe的BitBucket上。