使用while循环而不是循环进行迭代

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; } } 

然后我可以打印小于1000的斐波那契数。

 for(let value of fibonacci()) { if(value > 1000) { break; } console.log(value); } 

对于这个例子, while循环代替for循环会更自然,类似于

 while(value of fibonacci() < 1000) { console.log(value); } 

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

这样会满足你吗?

 var sequence = fibonacci(); var value; while ((value = sequence.next()) < 1000) { console.log(value); } 

再加上,甚至更好的解决scheme可能是这样的:

 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); } 

有两种可能的方法我会继续这个,给予其他语言,支持这种行为:

1)一个使用和谐代理,这将让你做元表(有点像在卢阿 ),并允许惰性iterables。 这将提供以下符号:

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

2)第二个使用take函数让你消耗一个迭代.forEach像在C#python中 。 这将允许以下表示法:

  takeWhile(fibGenerator,(item) => item<1000).forEach(... // consume with predicate 

第一种方法 – 使用和谐代理

注意…通过对象循环。 它并不能保证顺序。 然而,你可以做类似下面的事情来得到一个惰性迭代的概念。

您必须使用--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 } 

它只会计算尚未提取的数字,这将允许您使用简单的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); 

(只是不要指望它会很快)

*(使用旧代理符号,因为新节点不支持节点,一旦得到支持就会更新)


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

第二种方法,使用迭代器Takefunction。

这就是你通常在C#这样的语言中使用的例子。

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

然后做一些像

 var res = takeWhile(fibIterator,function(item){ return item<1000; }); res.forEach(function(){ ... 

或者通过计数:

 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 
 function *bar(){ yield 1; yield 2; yield 3; return 4; } var value, g = bar(); while((value = g.next()).value){ console.log(value); } //Object {value: 1, done: false} //Object {value: 2, done: false} //Object {value: 3, done: false} //Object {value: 4, done: true} 

是的,可以通过使用常规生成器方法来完成此操作。

 var fib = fibonacci(), value; while( (value = fib.next()) < 1000 ) { console.log(value); } 

尽pipe我似乎更喜欢处理下一个调用和处理StopIteration (如果序列是有限的)的处理语句。