生成器函数是 ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同
# 2.1 声明与调用
# *
的位置没有限制
function * gen(){
console.log('hello generator');
}
gen(); // 函数没有执行,而是返回了一个生成器对象
let iterator = gen();
console.log(iterator) // gen {<suspended>}
iterator.next(); // hello generator 【{value: undefined, done: true}】
# 函数代码分隔符 yield
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
- yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
function * gen(){
yield '一只没有耳朵';
yield '一只没有尾巴';
return '真奇怪';
}
let iterator = gen();
console.log(iterator.next()); // {value: "一只没有耳朵", done: false}
console.log(iterator.next()); // {value: "一只没有尾巴", done: false}
console.log(iterator.next()); // {value: "真奇怪", done: true}
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(222);
yield '一只没有尾巴';
console.log(333);
yield '真奇怪';
console.log(444);
}
let iterator = gen();
iterator.next(); // 111 【{value: "一只没有耳朵", done: false}】
iterator.next(); // 222 【{value: "一只没有尾巴", done: false}】
iterator.next(); // 333 【{value: "真奇怪", done: false}】
iterator.next(); // 444 【{value: undefined, done: true}】
实际案例1:发号器
function * createIdMaker() {
let id = 1
while(true){
yield id++
}
}
const idMaker = createIdMaker()
console.log(idMaker.next().value) // 1
console.log(idMaker.next().value) // 2
console.log(idMaker.next().value) // 3
实际案例2:使用 Generator 函数实现 iterator 方法
原来的
const obj = {
store: ['foo', 'bar', 'baz']
[Symbol.iterator]: function() {
let index = 0
const self = this
return {
next: function(){
return {
value: self.store[index],
done: index++ >= self.store.length
}
}
}
}
}
改进后
const obj = {
store: ['foo', 'bar', 'baz']
[Symbol.iterator]: function * () {
for (const item of this.store){
yield item
}
}
}
# 传递实参
- next 方法可以传递实参,作为 yield 语句的返回值
function * gen(arg) {
console.log(arg);
const one = yield 111;
console.log(one);
const two = yield 222;
console.log(two);
const three = yield 333;
console.log(three);
}
let iterator = gen('AAA');
console.log(iterator.next()); // AAA {value: 111, done: false}
console.log(iterator.next('BBB')); // BBB {value: 222, done: false}
console.log(iterator.next('CCC')); // CCC {value: 333, done: false}
console.log(iterator.next('DDD')); // DDD {value: undefined, done: true}
# 生成器函数实例
异步编程实例,1s后控制台输出111,2s后输出222,3s后输出333
回调地狱
setTimeout(()=>{
console.log(111);
setTimeout(()=>{
console.log(222);
setTimeout(()=>{
console.log(333);
}, 3000);
}, 2000);
}, 1000);
生成器函数
function one() {
setTimeout(()=>{
console.log(111);
iterator.next();
}, 1000);
}
function two() {
setTimeout(()=>{
console.log(222);
iterator.next();
}, 2000);
}
function three() {
setTimeout(()=>{
console.log(333);
iterator.next();
}, 3000);
}
function * gen() {
yield one();
yield two();
yield three();
}
let iterator = gen();
iterator.next();