ES6-Generator
基本概念
Generator 函数可以理解为是一个包含了多个内部状态的状态机;此外,执行 Generator 函数会返回一个遍历器对象,是一个遍历器对象生成器,返回的遍历器可以依次遍历 Generator 函数内部的每一个状态
Generator 函数与普通函数有几点不同:
function 命令与函数名之间有个 * 号,函数内部使用 yield 语句定义不同的内部状态
1
2
3
4
5function* exampleGenerator() {
yield 'hello'
yield 'world'
return 'lalala'
}调用后函数并不执行,返回的也不是运行结果,而是一个指向内部状态的遍历器对象,通过调用 next 方法可以移向下一个 yield;每次调用 next 方法,就会返回一个有着 value 和 done 两个属性的对象
1
2
3
4
5
6const example = exampleGenerator()
example.next() // => { value: 'hello', done: false }
example.next() // => { value: 'world', done: false }
example.next() // => { value: 'lalala', done: true }
example.next() // => { value: undefined, done: true }
yield 语句实际上是暂停遍历的“标志”,next 方法遇到 yield 语句就暂停执行后面的操作,并将紧跟在 yield 后面的表达式的值作为返回对象的 value 属性,这个求值是惰性求值
需要注意,如果 yield 语句用在另一个表达式中,必须放在圆括号里,如果用于函数参数或者位于赋值表达式右边则可以不加
1 | function* example() { |
next 方法可以带一个参数,该参数会被当做上一条 yield 语句的返回值,通过这种方法可以在 Generator 函数运行的不同阶段从外部向内部注入不同的值从而调整函数行为
1 | function* example(x) { |
在上面的代码中,第一次调用 next 返回 x + 1 的值,第二次调用传入参数 12,将上一步 yield 的值设置为 12,因此 a = 24;第三次传入 20,同样的,b = 20,因此最终返回 49
需要注意的是,next 方法的参数表示上一条 yield 语句的返回值,因此第一次使用 next 方法时传递参数是无效的,如果想在第一次调用 next 方法时就能输入值,可以在 Generator 函数外面在包一层
1 | function wrapper(generatorFn) { |
使用 for…of 循环可以自动遍历 Generator 函数生成的 Iterator 对象,不需调用 next 方法
1 | function* fn() { |