使用ES6的generator实现可变的无限集合

  无限且惰加载的集合是许多语言的特性,现在可以使用ES6的新iterator和generator实现了。通常我们使用数组Array在内存中建立有限大小的集合,如果是无限大则可能会消耗大量内存,那么为什么需要无限的集合?因为很多时候我们无法事先确定集合的大小,只能假设这个集合是可变的无限大了。

Iterator

  允许构建无限集合,内建语言的构造器用来遍历这个无限集合,也就是可以使用for-of循环遍历,为了构造一个Iterable,你需要返回一个key为Symbol.iterator的iterator 实例,这个iterator方法中只需要一个next()方法,用来返回一个结果对象,其中包含done和值,前者表示是否有更多元素,后者就是包含真正的元素值,代码如下:

var naturalNums = {
  [Symbol.iterator]: (()=>{
    let i = 0;
    return {
      next: () => {
            return {done: false, value: i++};
      }
    }
  })
};

上述无限大的集合构建后,你可以使用for-of循环遍历:

for(let i of naturalNums){
  if(i > 10) break; // 千万别忘记中断,否则一直无限循环下去
  console.log(i);
}

Generator

  Generator是基于iterator的语法糖,可以节省很多繁琐的代码,让你集中业务逻辑,代码如下:

var naturalNums = function* (){
  let i = 0;
  while(true){
    yield i++;
  }
}

这个代码比前面iterator简洁,使用方法是一样:

for(let i of naturalNums()){ //这里函数名称与前面调用不同
  if(i > 10) break;
  console.log(i);
}

Gentoo库包 - Generator工具

  虽然generator可以方便构建一个无限大且懒惰加载的集合,但是无法使用流处理如filter map 和reduce等方法,而Gentoo工具则可以提供类似方法,比如前面案例如下:

const sum =
  gentoo.chain(gentoo.range(1, Number.POSITIVE_INFINITY))
      .filter(isPrime)
      .limit(100)
      .reduce((memo, val) => memo + val, 0)
      .value()

 

Javascript专题