本文深入解析 JavaScript 生成器(Generator)的核心机制。通过 function* 定义生成器函数,利用 yield 关键字实现代码暂停与恢复。文章演示了如何调用生成器对象获取值,并展示其在 for...of 循环中的自动迭代用法,帮助开发者掌握异步编程与无限序列处理技巧。
什么是生成器?
生成器本质上是函数内部的一段特殊代码逻辑。
- 当执行到返回值后,生成器会自动暂停执行。
- 此时,调用程序可以请求取消暂停,并获取下一个值。
这种“返回”机制不同于传统的函数 return 语句,因此被赋予了一个专用术语——yield。
不同编程语言中生成器的语法存在差异。JavaScript 的生成器语法与 PHP 类似,但细节区别显著。若期望两者行为完全一致,可能会产生混淆。
在 JavaScript 中使用生成器,需遵循以下步骤:
- 定义专用的生成器函数。
- 调用该函数以创建一个生成器对象实例。
- 在循环中使用该生成器对象,或直接调用其 next 方法。
我们将通过以下简单程序作为起点,逐步执行上述每个步骤:
// File: sample-program.js
function *createGenerator() {
for(let i=0;i<20;i++) {
yield i
}
}
const generator = createGenerator()
console.log(generator.next())
console.log(generator.next())
运行这段代码,将得到如下输出结果:
$ node sample-program.js
{ value: 0, done: false } { value: 1, done: false }
接下来解释该程序的工作原理。
生成器函数
首先,代码中定义了生成器函数:
function* createGenerator() {
for(let i=0;i<20;i++) {
yield i
}
}
function 关键字后的 * 符号表明这是一个生成器函数。以下写法均属于有效的生成器函数定义方式。
function*createGenerator
function* createGenerator
function *createGenerator
注意,* 并非函数名的一部分,而是 function* 整体符号用于定义生成器。
调用生成器函数
定义生成器函数后,我们调用它并赋予结果一个变量名。
// 注意:当调用时,没有 *。 * 不是函数名称的一部分
// `function *` 是用于定义生成器函数的符号
const generator = createGenerator()
需注意:createGenerator 函数本身不返回传统意义上的值。生成器函数被调用时,总是返回一个实例化的 Generator 对象。
该生成器对象包含一个 next 方法。调用 next 会在生成器函数内部执行代码。
function* createGenerator() {
for(let i=0;i<20;i++) {
yield i
}
}
这一点至关重要,需再次强调:直接调用生成器函数并不会执行其内部代码,而是创建生成器对象。必须在该对象上调用 next 方法,才会触发生成器函数内的代码执行。
首次调用生成器对象的 next 时,内部代码会一直执行,直到遇到 yield 语句。执行到 yield 后,JavaScript 会暂停代码执行,next 返回一个对象,其中包含 yield 语句中的值。
当第二次(或第三次、第四次等)调用 next 时,代码会从上次中断处取消暂停并继续运行。变量(如本例中的 i)会保持其值。当代码再次遇到 yield 语句时,函数会再次暂停,并返回包含 yield 值的对象。
这就是我们需要调用两次 next 的原因。
console.log(generator.next())
console.log(generator.next())
执行后将得到以下输出:
{ value: 0, done: false } { value: 1, done: false }
当生成器函数中的代码执行完毕后,后续对 next 的任何调用都会返回一个对象,其 value 为 undefined,且 done 属性设为 true。
{ value: undefined, done: true }
生成器和循环
虽然可以手动在生成器对象上调用 next,但主要用途是在循环中使用。查看以下稍作修改的程序:
// File: sample-program.js
@highlightsyntax@jscript
function *createGenerator() {
for(let i=0;i<5;i++) {
yield i
}
}
const generator = createGenerator()
for(const value of generator) {
console.log(value)
}
当在 for...of 循环中使用生成器对象时,每次循环迭代都会在生成器对象上调用 next,并将产生的值赋给变量(即上面的 value)。运行该程序将输出以下内容:
$ node sample-program.js 0 1 2 3 4
在下一篇文章中,我们将深入探讨 for...of 循环,并探索如何为 JavaScript 提供一种内置方法来遍历任何对象。
总结
到此这篇关于 JavaScript 生成器(Generator)的文章就介绍到这了,更多相关 JavaScript 生成器(Generator)内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!