参考:Generator 函数的含义与用法
ES6 Generator
1.基本用法
Generator函数两个特征:
- 函数名与function之间有个
* - 函数内部使用yield表达式
每次调用next方法,返回一个对象,包含value和done,value的值即yield后面表达式的值
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 }
2.yield
Generator函数内部,找两个关键字: yield 和 return
注意:y = yield 1 + 1; 此时y是undefined,并非2
遇到yield就暂停后面的操作,并把紧跟在yield后面的表达式的值,作为返回对象的value值属性。并且每次执行next才会去找yield,依次往下找,找不到yield则找return;
3.next方法的参数
yield表达式本身没有返回值,或者说总是返回 undefined ,我们看下面这个例子
function* helloWorldGenerator() {var y = yield 1 + 1return y}let hw = helloWorldGenerator()console.log(hw.next()) // { value: 2, done: false }console.log(hw.next()) // { value: undefined, done: true }
第一个next返回对象的value是 表达式 1+1 的值,但整个 yield 1+1 是没有返回值的,所以最后y为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 }
对于前两个g.next方法,由于没有传参,所以reset都是undefined,函数执行下去,都会走i++,所以第一次和第二次比value都在+1。当第三个next执行时,传了参数true,此时上一个yield表达式返回true, reset为true, 函数往下执行;i = -1,然后走for循环 i++; 所以最后i = 0
4.循环遍历
for of
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
for of 循环可以自动遍历Generator函数运行时生成的Iterator对象,此时无需调用next方法
循环会在next方法返回的对象的done属性为true时终止,并且结果不包含改对象的value;所以上面最终打印结果没有6
Array.from和扩展符
除了for…of循环以外,扩展运算符(…)、解构赋值和Array.from方法内部调用的,都是遍历器接口。这意味着,它们都可以将 Generator 函数返回的 Iterator 对象,作为参数。
function* numbers () {yield 1yield 2return 3yield 4}// 扩展运算符[...numbers()] // [1, 2]// Array.from 方法Array.from(numbers()) // [1, 2]
5.next()、throw()、return()方法
next()、throw()、return()这三个方法本质上是同一件事,可以放在一起理解。它们的作用都是让 Generator 函数恢复执行,并且使用不同的语句替换yield表达式。
next()是将yield表达式替换成一个值,前面有提到,即将参数作为上一个yield表达式的返回值;这里就不举例
throw()是将yield表达式替换成一个throw语句
gen.throw(new Error('出错了')); // Uncaught Error: 出错了// 相当于将 let result = yield x + y// 替换成 let result = throw(new Error('出错了'));
return()是将yield表达式替换成一个return语句
gen.return(2); // Object {value: 2, done: true}// 相当于将 let result = yield x + y// 替换成 let result = return 2;
6.generator函数的this
function* g() {}g.prototype.hello = function () {return 'hi!';};let obj = g();obj instanceof g // trueobj.hello() // 'hi!'
注意:generator函数实例化对象,不能使用关键字new!!!
function* g() {this.a = 11;}let obj = g();obj.next();obj.a // undefined
Generator函数在this对象上添加一个属性a,但是obj对象拿不到
