JavaScript:生成器

本文详细介绍了JavaScript中的生成器,包括如何定义、创建、执行生成器,以及中断、提前终止生成器的方法。生成器通过yield关键字实现执行的暂停和恢复,可以用来管理复杂流程和迭代操作。同时,文章讨论了向生成器传参、处理错误以及自动迭代生成器对象等高级特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生成器(函数)是一种特殊的函数,在生成器的函数块内可以暂停和恢复代码的执行。


主要参考资料:

  • 《JavaScript 高级程序设计(第4版)》- P192(217/931)

定义生成器

在使用关键字 function 定义函数对象时,通过在关键字 function 后面添加星号 * 来定义生成器。

不能使用箭头函数定义生成器。

星号 * 不受其两侧的空格影响。

示例:

// 定义生成器
function *generator() {}
function * generator01() {}
function* generator02() {}

let generator03 = function *() {}

// 在对象字面量中简写函数时
let obj = { 
	*generator04() {}
}

创建生成器对象

调用生成器并不会执行生成器中的代码,而是会创建一个生成器对象。

示例:

function *generator() {
	return 'finished'
}

// 创建生成器对象
let generatorObj = generator()

生成器对象是迭代器。生成器对象实现了接口 Iterator ,拥有方法 next() 。但生成器对象的方法 next() 并不是用于迭代可迭代对象的。

生成器对象是可迭代对象。生成器对象也实现了接口 Iterable ,而且生成器对象的默认迭代器函数返回生成器对象自身。


执行生成器

想要执行生成器中的代码,必须调用对应的生成器对象的方法 next() 。

生成器对象拥有方法 next() ,用于使生成器进入或恢复执行状态。

【有待补充】
生成器对象的方法 next() :

  • 返回值:
    对象,结构为生成器结果:
    • 属性 done ,布尔值,表示生成器是否已经执行完毕。
    • 属性 value ,生成器的返回值。

示例:

function *generator() {
	return 'finished'
}

let generatorObj = generator()

// 执行生成器
console.log(generatorObj.next())  // { done: true, value: 'finished' }

生成器会对每个生成器对象执行生成器的行为区分作用域。

每个生成器对象的生成器执行是独立的,多个生成器对象之间的执行生成器的行为不会相互影响。


中断生成器

在生成器中使用关键字 yield 来指定生成器中断执行的位置。

生成器执行的中断、恢复:

  • 生成器在执行时遇到关键字 yield ,会停止执行,函数作用域的状态会被保留。
  • 当生成器的生成器对象调用方法 next() 时,生成器会从停止执行的位置开始恢复执行,直到遇到关键字 yield 或 return ,生成器才会停止执行。

关键字 yield 像关键字 return 一样可以返回值。

关键字 yield 只能在生成器的函数块中使用,不能在普通函数的函数块中使用。

示例:

function *generator() {
	yield '01'  // 中断执行,并返回值
	yield '02'
	return 'finished'
}

let generatorObj = generator()

console.log(generatorObj.next())
console.log(generatorObj.next())
console.log(generatorObj.next())

// 输出:
// { done: false, value: '01' }
// { done: false, value: '02' }
// { done: true, value: 'finished' }

提前终止生成器

通过调用生成器对象的方法 return() ,提前终止生成器。

生成器对象的方法 return() 会强制生成器进入关闭状态。

生成器对象的方法 return() :

  • 功能:
    强制生成器进入关闭状态。

  • 接收一个参数:
    任意值,用作返回值对象的属性 value 的值。

  • 返回值:
    对象,结构为生成器结果:

    • 属性 done ,值为 true ,表示生成器终止执行(执行完毕)。
    • 属性 value ,方法接收的第一个参数。

示例:

function *generator() {
	yield '01'
	yield '02'
	return 'finished'
}

let generatorObj = generator()

console.log(generatorObj.next())
console.log(generatorObj.return('Exiting early'))  // 提前终止生成器
console.log(generatorObj.next())

// 输出:
// { done: false, value: '01' }
// { done: true, value: 'Exiting early' }
// { done: true, value: undefined }

向生成器抛出错误

通过调用生成器对象的方法 throw() ,向生成器抛出错误。

生成器对象的方法 throw() 会恢复生成器的执行,直到遇到关键字 yield 或 return ,生成器才会停止执行。

生成器对象的方法 throw() :

  • 功能:
    向生成器抛出错误。

  • 接收一个参数:
    任意值,错误信息。

  • 返回值:
    对象,结构为生成器结果:

    • 属性 done ,布尔值,表示生成器是否终止执行(执行完毕)。
    • 属性 value ,生成器的返回值。

生成器处理生成器对象抛出的错误:

  • 如果生成器没有处理生成器对象抛出的错误,生成器就会关闭。
  • 如果生成器处理了生成器对象抛出的错误,生成器继续正常执行。

示例:

  • 向生成器抛出错误

    function *generator() {
    	yield '01'
    	yield '02'
    	return 'finished'
    }
    
    let generatorObj = generator()
    
    console.log(generatorObj.next())
    
    try {
    	console.log('Returned Value of throw(): ', generatorObj.throw('Error01'))  // 向生成器抛出错误
    } catch(e) {
    	console.log('Error: ', e)
    }
    
    console.log(generatorObj.next())
    
    // 输出:
    // { done: false, value: '01' }
    // Error: Error01
    // Returned Value of throw(): { done: true, value: undefined }
    
  • 生成器处理错误

    function *generator() {
    	try {
    		yield '01'
    	} catch(e) {  // 捕获错误
    		console.log('Generator dealed error: ', e)
    	}
    	yield '02'
    	return 'finished'
    }
    
    let generatorObj = generator()
    
    console.log(generatorObj.next())
    
    try {
    	console.log('Returned Value of throw(): ', generatorObj.throw('Error02'))
    }
    catch(e) {
    	console.log('Error: ', e)
    }
    
    console.log(generatorObj.next())
    
    // 输出:
    // { done: false, value: '01' }
    // Generator dealed error: Error02
    // Returned Value of throw(): { done: false, value: '02' }
    // { done: true, value: 'finished' }
    

生成器对象向生成器传参

生成器对象在调用方法 next() 时,为 next() 提供参数,可以向生成器传递这个参数。

生成器的关键字 yield 会接收生成器对象传递的参数。

示例:

function *generator() {
	let data = yield
	
	console.log(data)
	data = yield
	
	console.log(data)
}

let generatorObj = generator()

// 生成器对象向生成器传参
generatorObj.next()       // 启动生成器
generatorObj.next('one')  // one
generatorObj.next('two')  // two

【补充】
生成器对象的方法 next() :

  • 功能:
    用于使生成器进入或恢复执行状态,并向生成器传参。

  • 接收一个参数:
    任意值,被生成器的关键字 yield 接收。

  • 返回值:
    对象,结构为生成器结果:

    • 属性 done ,布尔值,表示生成器是否已经执行完毕。
    • 属性 value ,生成器的返回值。

自动迭代生成器对象

生成器对象是可迭代对象,可以对生成器对象使用自动迭代。

示例:

function *generator() {
	yield '01'
	yield '02'
	return 'finished'
}

let generatorObj = generator()

// 自动迭代生成器对象
for(const item of generatorObj) {
	console.log(item)
}

// 输出:
// 01
// 02

生成器迭代可迭代对象

生成器通过在关键字 yield 和可迭代对象之间添加星号 * ,来迭代一个可迭代对象。

星号 * 不受其两侧的空格影响。

生成器迭代可迭代对象的主要过程:

  1. 创建可迭代对象的迭代器。
  2. 调用迭代器的方法 next() 。
  3. 判断迭代器结果的属性 done 。
  4. 如果迭代器结果的属性 done为 false ,则使用关键字 yield 返回迭代器结果的属性 value 的值。并转到过程 2 。
  5. 如果迭代器结果的属性 done为 true,则获取迭代器结果的属性 value 的值。
  6. 结束。

因此生成器会将可迭代对象的迭代器最终返回的迭代器结果 { done: true, value: any } 的属性 value 的值作为 yield* 最终的值,但不会停止执行来返回 yield* 的值。

示例:

function *generator() {
	yield* [1, 2]  // 迭代可迭代对象
	return 'finished'
}

let generatorObj = generator()

console.log(generatorObj.next().value)
console.log(generatorObj.next().value)
console.log(generatorObj.next().value)

// 输出:
// 1
// 2
// finished

function *generator01() {
	console.log('yield*: ', yield* [1, 2])
	return 'finished'
}

generatorObj = generator01()

console.log(generatorObj.next().value)
console.log(generatorObj.next().value)
console.log(generatorObj.next().value)

// 输出:
// 1
// 2
// yield*: undefined
// finished

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值