一,Generator
函数介绍
1.Generator
函数是 ES6
提供的一种异步编程解决方案。
2.Generator
函数像一个状态机,保存了许多状态,并将这些状态作为遍历器对象返回。
二,Generator
函数基本形式
1.为了和传统的函数区别,Generator
函数function
后面会跟着一个*
号,函数内部通常有许多yield
后跟着表达式表示状态。
functurn* fn(){
yield xxx
yield xxx
}
三,Generator
函数特性
1.传统的函数被调用后会立马执行,且一次执行到return
结束,而Generator
函数被调用时不会立马执行内部的语句,而是返回了一个遍历器对象,
2.由遍历器对象的next()
方法启动,遇到yield
后又会暂停,直到下一个next()
才会继续启动。
{
function* gen()
{
yield 1;
console.log(yield 2); // undefined
yield 3;
return 4;
}
let ge=gen() //返回一个遍历器对象
console.log(ge.next()) // {value: 1, done: false}
console.log(ge.next()) // {value: 2, done: false}
console.log(ge.next()) // {value: 3, done: false}
console.log(ge.next()) // {value: 4, done: true}
console.log(ge.next()) // {value: undefined , done: true}
}
四,yield
表达式 [jiːld]
1.yield
表达式只能在Generator
函数中使用,在其他地方使用会报错。
2.yield
表达式在其他表达式中被使用时必需加一对括号
3.当代码运行到yield
时会暂停,下一次再从该位置继续向后执行。
4.注意yield
表达式的返回值是undefined
,而不是跟在yield
后面表达式的值,但可被next()
传入的参数赋值
5.yield*
表达式用来在一个 Generator
函数里面执行另一个 Generator
函数
function* a()
{
yield 1;
yield 2;
}
function* b()
{
yield* a()
yield 3;
yield 4;
}
五,next()
方法。
1.next
方法使Generator
函数开始执行到下一个yield
2.如上所说在函数内部yield
本身返回值是undefind
,但是可以通过next()
带一个参数,为上一个yield
表达式赋值
3.next()
方法的返回值是包含value
,和done
字段的对象,其中value
是yield
表达式的值,done
表示是否结束
{
function* foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}
var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }
}
4.Generator
函数执行解析:
(1)next()
不带参数,
当第一次执行a.next()
时,程序执行到 yield (x+1)
暂停,此时yield (x+1)
的值是undefined
,而在next()
返回对象的value
是yield
后面表达式的值6
。
当第二次执行a.next()
时,程序从yield(x+1)
开始,而在表达式中,yield
的返回值是undefined
,因此y=2*undefined
, 所有y=NaN
,程序会执行到yield(y/3)
暂停,NaN/3=NaN
,所以表达式值为NaN
当第三次执行a.next()
时,程序从yield(y/3)
开始,z=undefined
, x+y+z=5+NaN+undefined=NaN
,返回NaN
。
(2)next()
带参数
当第一次执行a.next()
时,程序执行到 yield (x+1)
暂停,此时表达式值为6
。
当第二次执行a.next(12)
时,程序从yield(x+1)
开始,next
方法的参数12
代表上一次yield
表达式的返回值,所以 y=2*yield(x+1)=2*12=24
, y=24
,程序会执行到yield(y/3)
暂停,24/3=8
,所以表达式值为8
。
当第三次执行a.next(13)
时,程序从yield(y/3)
开始,z=13
, x+y+z=5+24+13=42
,返回42
。
六,Generator
函数和构造函数的区别
1.Generator
函数总是返回一个遍历器,ES6
规定这个遍历器是 Generator
函数的实例,也继承了 Generator
函数的prototype
对象上的方法,
function* g() {}
g.prototype.hello = function () {
return 'hi!';
};
let obj = g();
obj instanceof g // true
obj.hello() // 'hi!'
2.Generator
函数g
返回的遍历器obj
,是g
的实例,而且继承了g.prototype
。但是,如果把g
当作普通的构造函数,并不会生效,因为g
返回的总是遍历器对象,而不是this
对象,所以Generator
函数也不能跟new
命令一起用。
function* g() {
this.a = 11;
}
let obj = g();
obj.next();
obj.a // undefined
参考:https://es6.ruanyifeng.com/#docs/generator