《十六》ES6+ 中的 Generator

Generator 生成器是 ES6 中新增的一种函数控制、使用的方案,可以让开发人员更加灵活地控制函数什么时候暂停执行、什么时候继续执行等。

在此之前,函数的终止条件通常是返回值或者抛出异常。

生成器函数是一种特殊的函数:

  1. 生成器函数使用 function* 进行函数声明。

    ES6 没有规定,function 与函数名之间的星号,写在哪个位置。下面的写法都能通过,但一般是第三种。

    function * foo(x, y) { ··· }
    function *foo(x, y) { ··· }
    function* foo(x, y) { ··· }
    function*foo(x, y) { ··· }
    

    如果 Generator 函数是一个对象的属性,可以简写成下面的形式:

    const obj = {
     * generatorMethod() {}
    }
    // 完整形式如下:
    const obj = {
     generatorMethod: function* () {}
    }
    
  2. 生成器函数内部可以通过 yield 语句来暂停函数的执行。
  3. 调用生成器函数,并不会执行生成器函数内部的代码,而是默认返回一个生成器对象。

    生成器对象是内部实现的特殊的迭代器对象。

    function* fn() {
    	console.log(1)
    }
    fn() // 会发现:fn 函数中的代码没有被执行。因为调用 fn() 只是会返回一个生成器
    
    要想执行生成器函数内部的代码,需要调用生成器函数返回的生成器对象的 next() 方法。
    // 定义一个生成器函数
    function* fn() {
    	console.log(1)
    }
    
    // 调用生成器函数会返回一个生成器对象
    const generator = fn()
    // 调用生成器对象的 next 方法才会执行生成器函数内部的代码
    generator.next() // 执行生成器函数代码,打印 1
    

生成器函数的 yield 语句:

调用生成器函数返回的生成器对象的 next() 方法,会执行生成器函数内部的代码,直到遇到生成器函数内部的 yield 语句,就会暂停代码的执行。如果想要继续往后执行,需要再次调用生成器对象的 next() 方法。

// 定义一个生成器函数
function* fn() {
	console.log(1)
	yield
	console.log(2)
}

// 调用生成器函数会返回一个生成器对象
const generator = fn()
// 调用生成器对象的 next 方法才会执行生成器函数内部的代码,直到遇到 yield 语句就会中断执行
generator.next() // 执行生成器函数代码,打印 1
// 要想继续执行,需要再次调用 next 方法
generator.next() // 继续执行生成器函数代码,打印 2

yield 语句后面可以跟一个表达式:

yield 语句后面可以跟一个表达式。

function* fn() {
	console.log(1)
	yield 50 + 50
	console.log(2)
}

yield 语句的返回值:

yield 语句默认返回 undefined。

function* fn() {
	console.log(1)
	// yield 语句默认返回 undefined
	const yield1Value = yield
	console.log(2, yield1Value)
}

const generator = fn()
generator.next()
generator.next()

请添加图片描述

yield*

yield* :可以看着是一种 yield 的语法糖。后面跟一个可迭代对象,会依次 yield 这个可迭代对象中的每个元素。

const names = ['Lee', 'Mary', 'Tom']
 
// 生成器函数返回一个生成器,是特殊的迭代器
function* generator() {
	yield* names

	// 相当于:
	// yield names[0]
	// yield names[1]
	// yield names[2]
}
const namesGenerator = generator()
console.log(namesGenerator.next())
console.log(namesGenerator.next())
console.log(namesGenerator.next())

请添加图片描述

生成器对象的方法:

next() 方法:

next() :用来执行生成器函数内部的代码,直到遇到 yield 或者 return 语句,就暂停代码的执行。

next() 方法的返回值:

调用生成器函数返回的生成器对象的 next() 方法,会返回一个包含 done 和 value 属性的对象。

  1. 如果是遇到 yield 暂停的,done 就为 false,value 为 yield 后面表达式的值。
  2. 如果是遇到 return 暂停的,done 就为 true,value 为 return 返回的值。
  3. 如果是函数执行完毕,done 就为 true,value 为 undefined(函数执行完毕默认返回 undefined,就相当于是遇到 return undefined,done 就为 true,value 为 undefined)。
function* fn() {
	console.log(1)
	yield
	console.log(2)
}

const generator = fn()
console.log(generator.next()) // {value: undefined, done: false}
console.log(generator.next()) // {value: undefined, done: false}

请添加图片描述

function* fn() {
	console.log(1)
	yield 50 + 50
	console.log(2)
}

const generator = fn()
console.log(generator.next()) // {value: 100, done: false}
console.log(generator.next()) // {value: undefined, done: false}

请添加图片描述

next() 方法的参数:

生成器函数返回的生成器对象的 next() 方法可以带一个参数,该参数会被当做上一个 yield 语句的返回值。

function* fn() {
	console.log(1)
	const yield1Value = yield
	console.log(2, yield1Value)
}

const generator = fn()
generator.next()
generator.next('这是第二个 next 的参数,会作为第一个 yield 的返回值')

请添加图片描述

return() 方法:

return() :用来直接结束生成器函数的执行。

function* fn() {
	console.log(1)
	yield
	console.log(2, yield1)
}

const generator = fn()
// 执行到第一个 yield 后,就直接结束生成器函数的执行
generator.next()
generator.return()

请添加图片描述

throw() 方法:

throw() :用来抛出异常并中断生成器函数的执行。

function* fn() {
	console.log(1)
	yield
	console.log(2, yield1)
}

const generator = fn()
generator.next()
generator.throw(new Error('出错了'))

请添加图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值