Generator 函数是 ES6 提供的一种异步编程解决方案
特点
- function关键字与函数名之间有一个星号;
- 函数体内部使用yield表达式,
调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
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 表达式
Generator 函数提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
-
遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
-
下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
-
如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
-
如果该函数没有return语句,则返回的对象的value属性值为undefined。
function* f() {
console.log('执行了!')
}
var generator = f();
setTimeout(function () {
generator.next()
}, 2000);
只有调用next方法时,函数f才会执行
yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
(function (){
yield 1;
})()
// SyntaxError: Unexpected number
yield表达式如果用在另一个表达式之中,必须放在圆括号里面
function* demo() {
console.log('Hello' + yield); // SyntaxError
console.log('Hello' + (yield)); // OK
}
用Generator 函数 实现Iterator 接口
let myIterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
}
[...myIterable] // [1, 2, 3]
协程的 Generator 函数实现
function* gen(x) {
var y = yield x + 2;
return y;
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }
next方法还可以接受参数
next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
function* gen(x){
var y = yield x + 2;
return y;
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }
for...of 循环
for...of循环可以自动遍历 Generator 函数时生成的Iterator对象
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
网友评论