-
概念
- ES6提供的解决异步编程的方案之一
- Generator函数是一个状态机,内部封装了不同状态的数据
- 用来生成遍历器对象,返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态
- 可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
-
特点
- Generator 函数是一个普通函数
- function关键字与函数名之间有一个星号
- 函数体内部使用yield表达式,定义不同的内部状态
- generator函数返回的是指针对象,而不会执行函数内部逻辑
- 调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回:
- {value: yield后的表达式结果/undefined, done: false/true}
- 再次调用next方法会从上一次停止时的yield处开始,直到最后
- yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值
- Generator 函数是一个普通函数
-
步骤
- 下面代码定义了一个 Generator 函数helloWorldGenerator,它内部有两个yield表达式(hello和world),即该函数有三个状态:hello,world 和 return 语句(结束执行)
function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator(); hw.next() //输出:{ value: 'hello', done: false } hw.next() //输出:{ value: 'world', done: false } hw.next() //输出:{ value: 'ending', done: true } hw.next() //输出:{ value: undefined, done: true }
- Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)
- 下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止
- 总结一下,调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束
-
与 Iterator 接口的关系
-
任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象
-
Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有 Iterator 接口
// 对象的Symbol.iterator属性; let myIterable = {}; myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 4; }; for(let i of myIterable){ console.log(i); } let obj = [...myIterable]; console.log(obj);
-
-
next 方法的参数
-
yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值
function* f() { for(var i = 0; true; i++) { var reset = yield i; if(reset) { i = -1; } } } var g = f(); g.next() // { value: 0, done: false } g.next() // { value: 1, done: false } g.next(true) // { value: 0, done: false }
-
-
for…of 循环
-
for…of循环可以自动遍历 Generator 函数运行时生成的Iterator对象,且此时不再需要调用next方法
function* foo() { yield 1; yield 2; yield 3; yield 4; yield 5; return 6; } for (let v of foo()) { console.log(v); } // 1 2 3 4 5 function* objectEntries() { let propKeys = Object.keys(this); for (let propKey of propKeys) { yield [propKey, this[propKey]]; } } let jane = { first: 'Jane', last: 'Doe' }; jane[Symbol.iterator] = objectEntries; for (let [key, value] of jane) { console.log(`${key}: ${value}`); } // first: Jane // last: Doe function* numbers () { yield 1 yield 2 return 3 yield 4 } // 扩展运算符 [...numbers()] // [1, 2] // Array.from 方法 Array.from(numbers()) // [1, 2] // 解构赋值 let [x, y] = numbers(); x // 1 y // 2 // for...of 循环 for (let n of numbers()) { console.log(n) } // 1 // 2
-
-
应用场景
-
案例参考:https://es6.ruanyifeng.com/#docs/generator#%E5%BA%94%E7%94%A8
-
异步操作的同步化表达
-
控制流管理
-
部署 Iterator 接口
-
作为数据结构
-
ES6之 Generator 函数(九)
最新推荐文章于 2024-08-28 19:59:39 发布