生成器是ES6新增的一种函数控制、使用方案,是一种特殊的可以传参的迭代器
通过function后面加个*构造一个生成器
yield后面的值为next执行后返回的done-value对象,参数为value的值
yield赋值的是下一次next传的参数
// 生成器函数,function后面加个*号 通过yield返回value
function* foo(){
yield 123
yield 456
return "结束" //会返回给第三次执行的value
}
const generator = foo()
// next方法返回值为{done,value}
console.log("第一次执行",generator.next()); //{done:false,value:123}
console.log("第二次执行",generator.next()); //{done:false,value:456}
console.log("第三次执行",generator.next()); //没有yield的时候done为true,值为return的内容{done:true,value:"结束"}
console.log("第四次执行",generator.next()); //继续执行done为true,值为undefined
next()也是可以接收参数的,通过接收yield的返回值获得下一个next携带的参数
// 生成器函数每一块的参数接收,通过yield赋值接收参数
function* foo(n){
console.log('n: ', n); //100
const n1 = yield 123
console.log('n1: ', n1); //200
const n2 = yield 456
console.log('n2: ', n2); //300
return "结束"
}
const generator = foo(100)
// next方法返回值为{done,value}
// generator.next(101) //第一个next一般是不传参的,没有上层yield 一般在函数执行的时候擦传
// generator.next(200)
// generator.next(300)
// generator.next(400)
// 对应也有return和throw方法
generator.next(101)
generator.next(200)
// {done:true,value:15} 终止生成器,后面next也不执行了
console.log(generator.return(15));
//抛出异常后 后续代码都不会执行,如果用try catch捕获 那么会执行一次next
// generator.throw(15)
// console.log("111");
generator.next(300)
generator.next(400)
可以使用生成器来替代迭代器,提高代码效率
// 生成器来替代迭代器
function* foo(arr) {
// for(const item of arr){
// yield item
// }
// 是上面的语法糖
yield* arr; //跟上一个可迭代对象
// 用于替代以下
// let index = 0;
// return {
// next: () => {
// if (index < arr.length) {
// //根据done为false返回值
// return { done: false, value: this.name[index++] };
// } else {
// return { done: true, value: undefined };
// }
// },
// };
}
const arr = [1, 2, 3, 4];
const generator = foo(arr);
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());
// 可迭代对象的可迭代协议用生成器方法
const objIterator = {
name: ["abc","def","hij"],
[Symbol.iterator]:function*(){ //可迭代协议
yield* this.name
}
}
for(const item of objIterator){
console.log('item: ', item);
}