上一篇文章介绍并实现了迭代器,生成器是一种特殊的迭代器, 特殊在于生成器是由生成器函数得到的,并不是我们构造的对象。对于生成器函数,ES6有一套专门的规范和关键字定义
思考:JS中函数执行可以中断吗?
普通函数执行时,除非抛出错误,导致线程结束,否则函数不会中途暂停
但是如果想让函数执行中暂停怎么办,如何得到函数中间值,或者运行中间赋值?
ES6中新增的一种函数控制、使用的方案:
- 首先,生成器函数来创造生成器
- 而后由生成器来控制生成器函数的执行
生成器函数
生成器函数是一个特殊的函数,与普通的函数区别如下
- 生成器函数需要在function的后面加一个符号:
*
- 生成器函数可以通过
yield
关键字来控制函数的执行流程 - 生成器函数的返回值是一个
Generator
(生成器),并不是return的值
function* foo() {
const value1 = 100;
yield;
const value2 = 200;
yield value2;
return 111;
}
生成器对象
生成器函数返回一个生成器对象,由生成器对象next
方法来控制每段代码的执行,return语句可以当做一个特殊的yield,return的返回值也会被视为yield的返回值来处理
// 函数返回值为一个生成器对象
const generator = foo();
// 执行第一段代码
console.log(generator.next()); // {value: undefined, done: false}
// 执行第二段代码
console.log(generator.next()); // {value: 200, done: false}
// 执行第三段代码
console.log(generator.next()); // { value: 111, done: true }
生成器传递参数
调用next函数的时候,可以给它传递参数,那么这个参数会作为上一个yield语句的返回值
function* foo(m) {
const value1 = 100 * m;
const n = yield value1; // 第一个yield前用到的参数m,由函数入参传递
const value2 = 200 * n;
yield value2; // 第二个yield前用到的参数n,第二个generator.next(n)传递
return 111;
}
const generator = foo(0.1);
console.log(generator.next()); // { value: 10, done: false }
console.log(generator.next(10)); // { value: 2000, done: false }
console.log(generator.next()); // { value: 111, done: true }
🚀注意
每次调用generator.next(),代码执行到yield为止,即yield value1,而n的赋值则由下个generator.next传递的参数决定
const n = yield value1;
生成器方法return,throw
- return
generator.return()相当在上个yield之后添加了一个return语句
function* foo() {
const value1 = 100;
yield value1;
//⭐return('提前结束')
const value2 = 200;
yield value2;
return 111;
}
const generator = foo();
console.log(generator.next()); // { value: 100, done: false }
console.log(generator.return('提前结束')); //⭐ { value: '提前结束', done: true }
console.log(generator.next()); // { value: undefined, done: true }
- throw
generator.throw()相当在上个yield之后添加了一个throw new Error语句
function* foo() {
const value1 = 100;
yield value1;
//⭐throw new Error('提前结束')
const value2 = 200;
yield value2;
return 111;
}
const generator = foo();
console.log(generator.next()); // { value: 100, done: false }
console.log(generator.throw('错误信息')); //⭐ 中断
console.log(generator.next()); // 不会执行