认识
一、认识
Generator
函数是 ES6
提供的一种异步编程解决方案,语法行为与传统函数完全不同。Generator
函数将 JavaScript
异步编程带入了一个全新的阶段。
二、语法
function* genFun() {
yield 1;
yield 2;
return 3;
}
const gen = genFun();
const result1 = gen.next();
console.log(result1); //{ value: 1, done: false }
const result2 = gen.next();
console.log(result2); // { value: 2, done: false }
const result3 = gen.next();
console.log(result3); // { value: 3, done: true }
2.1 *
*
紧跟在function
关键字后面, 用于声明这是一个 Genearator
函数。
function* fun(){}
2.2 yield
由于 Generator
函数返回的遍历器对象,只有调用next
方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield
表达式就是暂停标志。
2.3 next()
由于 Generator
函数返回的遍历器对象,只有调用next
方法才会遍历下一个内部状态
参数: yield
表达式本身没有返回值,或者说总是返回undefined
。next
方法可以带一个参数,该参数就会被当作上一个yield
表达式的返回值。注意,由于next
方法的参数表示上一个yield
表达式的返回值,所以在第一次使用next
方法时,传递参数是无效的。V8
引擎直接忽略第一次使用next
方法时的参数,只有从第二次使用next
方法开始,参数才是有效的。从语义上讲,第一个next
方法用来启动遍历器对象,所以不用带有参数。
function* genFun() {
console.log(yield 1); // 哈哈
console.log(yield 2); // 嘻嘻
return 3;
}
const gen = genFun();
const result1 = gen.next(); // 第一个 next 用于启动遍历器对象, 传参无效
console.log(result1); //{ value: 1, done: false }
const result2 = gen.next("哈哈"); // 为第一个 yield 提供返回值
console.log(result2); // { value: 2, done: false }
const result3 = gen.next("嘻嘻"); // 为第二个 yield 提供返回值
console.log(result3); // { value: 3, done: true }
返回值
const gen = genFun();
const result = gen.next();
result = {
value: 表示当前的内部状态的值
done: 是一个布尔值,表示是否遍历结束
}
运行逻辑
-
遇到
yield
表达式,就暂停执行后面的操作,并将紧跟在yield
后面的那个表达式的值,作为返回的对象的value
属性值。 -
下一次调用
next
方法时,再继续往下执行,直到遇到下一个yield
表达式。 -
如果没有再遇到新的
yield
表达式,就一直运行到函数结束,直到return
语句为止,并将return
语句后面的表达式的值,作为返回的对象的value
属性值。 -
如果该函数没有
return
语句,则返回的对象的value
属性值为undefined
。
三、返回值
Generator
函数并不执行,返回也不是函数的执行结果,而是一个指向内部状态的遍历器对象 Iterator Object
。
const gen = genFun();
gen = Object [Generator] {}
四、运行机制
4.1 Generator 函数
Genearator
函数不会执行, 只返回一个指向内部状态的遍历器 Iterator Object
。
4.2 Interator 遍历器
Genearator
函数返回了一个指向内部状态的遍历器 Iterator Object
。我们接下来必须调用遍历器对象的next
方法,使得指针移向下一个状态。也就是说,每次调用next
方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield
表达式(或return
语句)为止。
每次调用遍历器对象的next
方法,就会返回一个有着value
和done
两个属性的对象。value
属性表示当前的内部状态的值,是yield
表达式后面那个表达式的值;done
属性是一个布尔值,表示是否遍历结束。
const gen = genFun();
const result = gen.next();
result = {
value: 表示当前的内部状态的值
done: 是一个布尔值,表示是否遍历结束
}
4.3 Genearator、Interator
换言之,Generator
函数是分段执行的,yield
表达式是暂停执行的标记,而next
方法可以恢复执行。
五、综合对比
5.1 yield vs return
yield
表达式与return
语句既有相似之处,也有区别。
yield
: 可以返回紧跟在语句后面的那个表达式的值, 每次遇到yield
,函数暂停执行,下一次再从该位置继续向后执行, 一个函数里面, 可以执行多次(或者说多个)yield
表达式
return
: 可以返回紧跟在语句后面的那个表达式的值, 而return
语句不具备位置记忆的功能, 一个函数里面,只能执行一次(或者说一个)return
语句
5.2 Genearator vs Function
普通函数: 执行函数内部代码, 返回函数执行结果
Generator
函数: 不执行函数内部代码, 返回一个指向内部状态的指针对象 Iterator Object
。
5.3 Generator vs Function Constructor
Generator
与new
使用,会报错foo is not a constructor