Generator, Iterable, Iterator

221 阅读3分钟

ES6生成器(Generator)

Generator是一个特殊的函数,函数体内部使用yield表达式,定义不同的内部状态,当执行Generator函数时,不会直接执行函数体,而是会返回一个遍历器对象(iterator)。

  • Generator函数内部可以使用yield表达式,定义内部状态
  • function关键字与函数名之间有一个*
function* generator() {
    console.log('start');
    yield 1
    yield 2
    yield 3
    console.log('end')
}
const iterator = generator() // 这时函数体并没有被执行,而是创建了一个iterator
// 当调用iterator的next方法时,函数体开始执行,
iterator.next() // 'start'  {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
iterator.next() // 'end'   {value: undefined, done: true}
  • 每调用一次next方法,函数体会从函数头部或上次停下来的地方开始执行,直到遇到下一个yield表达式或者return语句时停止
  • yield表达式后面的值会作为next方法返回的对象的value属性值
  • return会作为iterator结束的标记,并且return的值会作为next方法返回的对象的value属性值

改写一下上面的例子

function* generator() {
    yield 1
    yield 2
    return 3
}
const iterator = generator()
// 当调用iterator的next方法时,函数体开始执行,
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: true}

Generator函数生成的iterator可以被for...of遍历

function* generator() {
    yield 1
    yield 2
    yield 3
}

const iterator = generator()
typeof iterator[Symbol.iterator] // 'function'

for (const val of iterator) {
    console.log(val)
}
// 1
// 2
// 3

在这里我们只需要知道Generator函数会生成一个iterator就够了,但实际上Generator函数远不止这些,这里我们不做详细介绍了,感兴趣的同学可以看看阮一峰Generator教程

一个对象怎么让它可迭代

添加一个名为 Symbol.iterator 的方法,返回一个迭代器(实现next方法)。

为了让 对象可迭代,我们需要为对象添加一个名为 Symbol.iterator 的方法。当 for..of 循环启动时,它会调用这个方法(如果没找到,就会报错)。这个方法必须返回一个 迭代器(iterator) —— 一个有 next 方法的对象。从此开始,for..of 仅适用于这个被返回的对象。当 for..of 循环希望取得下一个数值,它就调用这个对象的 next() 方法。next() 方法返回的结果的格式必须是 {done: Boolean, value: any},当 done=true 时,表示迭代结束,否则 value 是下一个值。

Iterable(可迭代对象)

Iterable 是指有 [Symbol.iterator] 属性的对象,这个属性 obj[Symbol.iterator] 就是 Iterator(迭代器)。也可以说可迭代对象是实现了 Symbol.iterator 方法的对象。

可迭代对象可以被 for..of 循环遍历,我们最常进行迭代操作的可迭代对象就是 Array,其实还有其他可迭代对象,例如 String、Set、Map、函数的 arguments 对象和 NodeList 对象等,这些对象都有默认的 Symbol.iterator 属性。

Iterator(迭代器)

Iterator 必须有 next() 方法,它每次返回一个 {done: Boolean, value: any} 对象,这里 done:true 表明迭代结束,否则 value 就是下一个要迭代的值。

let someString = "hi";
typeof someString[Symbol.iterator];          // "function"

let iterator = someString[Symbol.iterator]();
iterator + "";                               // "[object String Iterator]"
 
iterator.next();                             // { value: "h", done: false }
iterator.next();                             // { value: "i", done: false }
iterator.next();                             // { value: undefined, done: true }