前言
由于Generator函数返回的遍历对象只有在调用next()方法的时候才会遍历下一个内部状态,就相当于提供了一种可以暂停执行的函数,yield表达式作为暂停标志就应运而生
定义与运行逻辑
yield关键字可以控制生成器Generator函数的停止和开始执行,也只能在生成器函数内部使用,可以说是生成器最重要最核心的一部分。
- 当生成器函数遇到
yield关键字时,执行就会立即停止并保留此时函数作用域的状态 - 此时的
yield关键字有点像函数的中间返回语句,yield会把紧跟其后的那个表达式的值作为返回对象的value属性值 - 当生成器对象调用
next()方法时,就会得到上一个yield返回对象的value属性值,且此时的生成器函数会处在done:false状态,意味着调用next()方法后生成器函数就会摆脱暂停状态继续执行(通过return关键词退出的生成器函数会处于done:true状态) - 如果没有再遇到
yield表达式,就会一直运行到函数结束,直到遇到return语句为止,并将return语句后面的表达式值作为返回对象的value属性值 - 该函数若没有return语句,则返回...当然是返回undefined啊
示例与应用
写者觉得读析具体的代码比看密密麻麻的文字要高效许多,有疑问上机试一番,豁然开朗
使用yield时生成器函数状态(done: false)与返回值
// 创建生成器函数
function* generatorFn() {
yield 1;
yield 'bar';
}
// 构建生成器对象
let generatorObj = generatorFn();
// 生成器对象调用next()函数,输出返回值
console.log(generatorObj.next());
// { value: 1, done: false }
console.log(generatorObj.next());
// { value: 'bar', done: false }
console.log(generatorObj.next());
// { value: undefined, done: true }
yield关键字必须直接位于生成器函数定义中
// 有效
function* validG() {
yield;
}
let vG = validG();
console.log(vG.next());
// { value: undefined, done: false }
// 无效
function* invalidGa() {
function a() {
yield;
}
}
let iGa = invalidGa();
console.log(iGa.next());
// { value: undefined, done: true }
// 注意和上一个示例对比,当把yield关键字置于嵌套的非生成器函数中,这里虽然没有报错,但是返
// 回的生成器函数状态为done: true,这说明yield在这里并没有起作用,读者可以试着注释掉yield,
// 输出依旧为{ value: undefined, done: true }
// 以上为依据,可以在yield关键字后加上返回值1,试试运行
function* invalidGa() {
function a() {
yield 1;
}
}
let iGa = invalidGa();
console.log(iGa.next());
// SyntaxError: Unexpected number
使用yield输入和输出
function* gFn() {
return yield 'foo';
}
let gObj = gFn();
// 第一次调用next()函数时即使输入参数也不会被使用,因为这一次调用是为了开始执行生成器函数
console.log(gObj.next());
// { value: 'foo', done: false }
console.log(gObj.next('bar'));
// { value: 'bar', done: true }
利用yield关键字的生成器可作为可迭代对象
function* nTimes(n) {
while(n--) {
yield;
}
}
for(let _ of nTimes(3)) {
console.log("foo");
}
// foo
// foo
// foo
利用yield产生可迭代对象
function* gFn() {
yield* [1, 2, 3];
// 星号(*)用于增强yield的行为,让它能够迭代一个可迭代对象
}
let gObj = gFn();
for(const x of gObj) {
// 等价于 const x 0f gFn()
console.log(x);
}
// 1
// 2
// 3
用yield实现递归算法
// 创造一个可迭代对象并返回递增的整数
function* nTimes(n) {
if (n > 0) {
yield* nTimes(n - 1);
yield n - 1;
}
}
for (const x of nTimes(3)){
console.log(x);
}
// 0
// 1
// 2
参考文献
《JavaScript高级程序设计》(第四版)
后话
这是第二篇啦,最近决定不考研冲前端,现在前端刚入门,基础还是很差的,每天都能学到新的东西,这种感觉真的非常棒,就是作为一个生物专业的大三狗,啊,我还有遗传学期中考试,大学不会有人上课还听课吧,不会吧......不会吧......不会吧......笑不出来了......啊!!!