一、状态机
function * stateFn(){ yield 'state1' var st2 = yield 'state2' yield step(st2) }
二、自定义遍历器生成函数
var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true}; } }; }
三、返回遍历器对象
为普通对象加同步遍历器接口,就可以用for of遍历对象了,可以用for of,yield*,Array.from,扩展操作符,解构赋值等方法遍历同步的iterator接口。
1、将无参的Generator函数加到对象的Symbol.iterator属性上,遍历对象
function* objectEntries() { let propKeys = Object.keys(this); for (let propKey of propKeys) { yield [propKey, this[propKey]]; } } const myObj = { name: 'Camille', age: 26 }; myObj[Symbol.iterator] = objectEntries; for (let [key, value] of myObj) { console.log(`${key}: ${value}`); }
//不用generator函数,也可以用for of 直接遍历Object.keys(myObj) const myObj = { name: 'Camille', age: 26 }; for (var key of Object.keys(myObj)) { console.log(key + ": " + myObj[key]); } //或者遍历Object.entries(myObj) const myObj = { name: 'Camille', age: 26 }; for (var [key,value] of Object.entries(myObj)) { console.log(key + ": " + value); }
2、直接遍历以对象为参数的Generator函数
function* objectEntries(obj) { let propKeys = Reflect.ownKeys(obj); for (let propKey of propKeys) { yield [propKey, obj[propKey]]; } } const myObj = { name: 'Camille', age: 26 }; for (let [key, value] of objectEntries(myObj)) { console.log(`${key}: ${value}`); }
//不用generator函数,也可以用for of 直接遍历Reflect.ownKeys(myObj) const myObj = { name: 'Camille', age: 26 }; for (var key of Reflect.ownKeys(myObj)) { console.log(`${key}: ${myObj[key]}`); }
四、惰性求值
next()方法的参数是上一个yield表达式的返回值,yield表达式暂停执行,next()恢复执行。
五、错误处理机制
function * errFn(){ try { yield 'es6 generator'; yield 'vue'; } catch(e) { console.log('内部捕获错误',e); } yield console.log('继续执行'); yield console.log('不受影响'); } var f = errFn(); f.next(); f.throw(new Error('外部抛出错误'));
function * errFn(){ try { yield 'es6 generator'; throw new Error('内部抛出错误'); //全局throw命令 yield 'vue'; } catch(e) { console.log('内部捕获错误',e); } } var f = errFn(); try { console.log('第一次运行next方法', f.next()); console.log('第二次运行next方法', f.next()); throw new Error('外部捕获错误'); //全局throw命令 console.log('第三次运行next方法', f.next()); } catch(e) { console.log('外部',e) }
1、throw()和throw语句的区别
throw()是generator函数的一个方法,throw()方法抛出的错误既可以被generator函数内部的catch语句捕获,也可以被generator函数外部的catch语句捕获。
throw语句用于创建自定义错误,它和generator函数没有任何关系,可以独立存在。既可以出现在generator函数内部的try语句中,也可以出现在generator函数外部的try语句中。外部的throw语句只能被generator函数外部的catch语句捕获,不能被generator函数内部的catch语句捕获。
2、generator函数内部的catch语句和外部的catch语句
generator函数内部的catch语句可以捕获generator函数内部的throw语句,也可以捕获外部的throw()方法。
generator函数内部的catch语句如果捕获到异常,将不影响下次遍历,还会附带执行一次next()方法。generator函数外部的catch语句一旦捕获到异常,就会中断执行try里面剩余的语句了。
3、什么情况下中断?
generator函数外部的catch语句一旦捕获到异常,就会中断执行try里面剩余的语句了。
调用了throw()方法,却没写任何catch语句,程序会中断执行。
六、generator函数的this
function* gen() { this.a = 1; yield this.b = 2; yield this.c = 3; } function F() { return gen.call(gen.prototype); } var f = new F(); f.next(); // Object {value: 2, done: false} f.next(); // Object {value: 3, done: false} f.next(); // Object {value: undefined, done: true} f.a // 1 f.b // 2 f.c // 3