用while循环而不是for循环迭代

Ran*_*lue 40 javascript ecmascript-6

ECMAScript 6为迭代引入了生成器,迭代器和语法糖.Node.JS v0.11.4带有标志

--harmony --use_strict --harmony_generators

了解以下发电机

function* fibonacci() {
  let previous = 0;
  let current = 1;

  while(true) {
    let temp = previous;
    previous = current;
    yield current = temp + current;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以打印小于1000的斐波纳契数.

for(let value of fibonacci()) {
    if(value > 1000) { break; }
    console.log(value);
}
Run Code Online (Sandbox Code Playgroud)

对于这个例子,while循环而不是for循环会更自然,类似于

while(value of fibonacci() < 1000) {
    console.log(value);
}
Run Code Online (Sandbox Code Playgroud)

可以使用while循环而不是循环来迭代迭代器for吗?

fsw*_*fsw 13

这样的事情会让你满意吗?

var sequence = fibonacci();
var value;
while ((value = sequence.next()) < 1000) {
    console.log(value);
}
Run Code Online (Sandbox Code Playgroud)

另外,甚至更好的解决方案可能是这样的:

function* fibonacci(limit){
  let previous = 0;
  let current = 1;

  while(previous + current < limit) {
    let temp = previous;
    previous = current;
    yield current = temp + current;
  }
}

for(let value of fibonacci(1000)) {
    console.log(value);
}
Run Code Online (Sandbox Code Playgroud)

  • @AaditMShah不,根据规范`function*`标记一个函数作为生成器. (3认同)
  • @fsw这是[生成器的符号](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-13.4). (2认同)
  • @fsw Mozilla目前对生成器的实现是一个笑话:)这就是原因.老实说,他们只是实现了生成器(以及`for ... of`其中_also_不在规范中)_before_它在规范中,这就是为什么他们做愚蠢的事情,比如当你'抛出异常'时迭代完成(比如在python生成器中,与C#生成器不同). (2认同)

Ben*_*aum 7

考虑到支持此行为的其他语言,我有两种可能的方法:

1)一个使用Harmony代理,它可以让你做元数据表(有点像lua)并允许懒惰的迭代.这将提供以下符号:

var arr = ...; // create the resource
for(var i=0;arr[i]<1000;i++){
    arr[i]; // consume fibonacci numbers
}
Run Code Online (Sandbox Code Playgroud)

2)第二个使用take函数让你.forEachC#python中使用类似的迭代.这将允许以下表示法:

 takeWhile(fibGenerator,(item) => item<1000).forEach(... // consume with predicate
Run Code Online (Sandbox Code Playgroud)

第一种方法 - 使用和声代理

注意...... for of循环遍历对象.它根本不保证订单.但是,您可以执行以下操作来获取惰性迭代的概念.

您必须使用--harmony_generators--harmony_proxies标志运行节点:

var arr = ...; // create an array and proxy it, use a generator internally
arr[50]; // will calculate the 50th fibonacci element and return it.
arr[100];// will calculate the 100th fibonacci element and return it.
for(var i=0;arr[i]<1000;i++){
   arr[i];//the i-th fibonacci number
}
Run Code Online (Sandbox Code Playgroud)

它只会计算尚未提取的数字,这将允许您使用一个简单的for循环.

这是如何*:

var cache = [];
var handler = {
        get: (function(){
          function fibIterator(){
             var t=0,a=0,b=0;
             return function(){
                t=a;
                a+=b;
                b=t;
                return a;
             }
          }
          var iterator = fibIterator();
          return function (target, fibNumber) {
                if (name in cache) {
                    return cache[name];
                }
                while(iterator < fibNumber){
                    // update indexes. 
                }
           })()
        }
    };
var arr = Proxy.create(handler);
Run Code Online (Sandbox Code Playgroud)

(只是不要指望它非常快)

*(使用旧的代理表示法,因为节点尚不支持新的代理表示法,一旦得到支持就会更新)


注意,在JavaScript中,因为函数可以通过闭包具有内部状态,所以您甚至不需要生成器

第二种方法,使用迭代器Take函数.

对于此用例,这是您通常使用C#等语言执行的操作.

function takeWhile(generating, predicate){
    var res = [],last;
    do{
        res.push(last=generating())
    }while(predicate(last));
    return res;
} 
Run Code Online (Sandbox Code Playgroud)

然后做类似的事情

var res = takeWhile(fibIterator,function(item){
    return item<1000;
});
res.forEach(function(){ ...
Run Code Online (Sandbox Code Playgroud)

或者按计数:

function take(generating,numToTake){
    var res = [],num;
    do{
        res.push(last=generating())
    }while(num++ < numToTake);
    return res;
}

var res = take(fibIterator,1000);//first 1000 numbers
Run Code Online (Sandbox Code Playgroud)