生成器函数
JavaScript ES6 生成器允许定义可以退出并稍后重新进入的函数,同时保留它们的上下文(变量绑定)。它们是使用function*(function关键字后跟一个星号) 定义的,并使用 yield 表达式来返回它们的结果。例如:
function* generateRange(end, start = 0, step = 1) {
let x = start - step;
while(x < end - step) yield x += step;
}
const gen5 = generateRange(5);
let x = gen5.next();
while (!x.done) {
console.log(x.value);
x = gen5.next();
} // Logs: 0, 1, 2, 3, 4
在上面的示例中,我们定义了一个生成器函数 ,generateRange 它将返回 start 和之间 end 的每个值,每次递增 step。我们使用生成器对象 Generator.prototype.next() 进行调用,直到它返回 {value: undefined, done: true} 以迭代生成器生成的值。
Symbol.iterator 指定对象的默认迭代器。通常,Symbol.iterator 使用生成器函数实现。例如:
const iterableXx = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
}
};
console.log([...iterableX]); // [1, 2]
正如您在此示例中所看到的,通过将生成器函数分配给其 Symbol.iterator 属性来使对象可迭代。如果您想迭代一些任意数据或创建一个可迭代的对象并在后台使用生成器函数,这可能会特别方便。
了解这两个概念的工作原理后,我们可以将它们结合起来创建一个范围生成器,类似于 Python 或 Ruby 的范围:
const range = (end, start = 0, step = 1) => {
function* generateRange() {
let x = start - step;
while(x < end - step) yield x += step;
}
return {
[Symbol.iterator]: generateRange
};
}
console.log([...range(7)]); // [0, 1, 2, 3, 4, 5, 6]
for (let i of range(8, 2, 2)) console.log(i); // Logs: 2, 4, 6