深入理解ES6-8.迭代器和生成器(1)

64 阅读2分钟

定义迭代器(Iterator)

迭代器是一个特殊对象:

  1. 含有 next() 方法,返回一个对象 {value:...,done:false}value 表示下一个要返回的值,done 表示后续是否还有值。当迭代到最后一个位置时,后续调用 next 方法会返回 {value:undefined,done:true}
  2. 有一个内部指针,指向当前集合中值的位置。

我们可以尝试自己模拟一个迭代器:

function createIterator(items){
    let i = 0;
    return {
        next(){
            const done = (i>=items.length);
            const value = done ? undefined : items[i];
            i++;
            return { done, value }
        }
    }
}
var iterator = createIterator([1,2,3]);
console.log(iterator.next());    // {value:1,done:false}
console.log(iterator.next());    // {value:2,done:false}
console.log(iterator.next());    // {value:3,done:false}
console.log(iterator.next());    // {value:undefined,done:true}
console.log(iterator.next());    // {value:undefined,done:true}

但其实不需要我们去模拟一个生成迭代器的函数,es6同时也为我们提供给了生成迭代器的函数 —— 生成器。

定义生成器(Generator)

生成器是返回迭代器的函数:

  1. 声明时要在 function 关键字后加上星号 * 来表示这是一个生成器
  2. 函数中间会用到关键字 yield,可以通过它来指定调用迭代器的 next() 方法后的返回值。不能在生成器以外使用 yield 关键字。
  3. 不能用箭头函数创建生成器。

我们可以看一下如何使用生成器生成迭代器:

function * createIterator(){
    yield 1;
    yield 2;
    yield 3;
}
// 连续调用3次next方法,分别返回1,2,3
var iterator = createIterator();

这样声明的 createIterator 生成器,和我们在上面模拟出来的 createIterator 方法,效果基本一致,对于生成的 iterator,就是一个具有 next 方法的迭代器。当然,我们要是传入一个数组,完全可以写成下面的形式:

// 用函数表达式创建生成器的写法
let createIterator = function * (items){
    for(let i=0;i<items.length;i++){
        yield items[i];
    }
}
var iterator = createIterator([1,2,3]);

在生成器中,每当执行一条 yield 语句后函数就会自动停止执行,直到再次调用迭代器的 next() 方法。