Generator(生成器)函数是es6提供的一种异步编程解决方案,Generator函数是一个状态机,封装了多个内部状态,执行Generator函数会返回一个遍历器对象。Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
Generator函数体内部使用yield表达式,定义不同的状态;调用Generator函数,该函数并不执行,返回的并不是函数运行结果,而是一个指向内部状态的指针对象;必须调用遍历器对象的next()方法,是的指针移向下一个状态。
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 }
yield表达式
yield后面的表达式,只有当调用next方法,内部指针指向该语句时才会执行 ,当遇到yield表达式,就会暂停执行后面的操作,并将紧跟在yield后面的表达式的值,作为返回的对象的value属性值。
与Iterator接口的关系
任意一个对象的Stmbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。
由于Generator函数就是遍历器生成函数,因此可以把Generator赋值给对象的Symbol.iterator属性,使得该对象具有Iterator接口。
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
原生的javascript对象没有遍历接口,无法使用for...of循环,通过Generator函数为它加上这个接口,就可以用了。
Generator是实现状态机的最佳结构。它减少了用来保存状态的外部变量,这样更简洁,更安全,更符合函数式编程。
var ticking = true;
var clock = function() {
if (ticking)
console.log('Tick!');
else
console.log('Tock!');
ticking = !ticking;
}
var clock = function* () {
while (true) {
console.log('Tick!');
yield;
console.log('Tock!');
yield;
}
}
应用
(1)异步操作的同步化表达
(2)控制流管理
(3)部署Iterator接口
利用Generator函数,可以在惹任意对象上部署Iterator接口
(4)作为数据结构