基本概念
Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
Generator 函数有多种理解角度。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator函数内部的每一个状态。
形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)
简单使用例子如下:
function* helloWorld() {
yield 'hello';
yield 'world';
return 'ending';
}
var m = helloWorld();
print(m.next().value)
print(m.next().done)
print(m.next().value)
print(m.next().done)
-----hello
-----false
-----ending
-----true
总结一下,调用 Generator函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
与 Iterator 接口的关系
任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。
由于 Generator函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有Iterator接口。
var myIterator = {};
myIterator[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
var iter = [...myIterator];
print(iter[0])
print(iter[1])
print(iter[2])
-----1
-----2
-----3
for…of 循环
for...of循环可以自动遍历Generator 函数运行时生成的Iterator对象,且此时不再需要调用next方法。
function *foo() {
yield 'a';
yield 'b';
yield 'c';
yield 'd';
return 'e';
}
for(let v of foo()) {
print(v);
}
-----a
-----b
-----c
-----d
利用 Generator 函数和for...of循环,实现斐波那契数列的例子。
function* fibonacci() {
let [prev, curr] = [0, 1];
for (; ;) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for(let n of fibonacci()) {
if(n>100) break;
print(n);
}
-----1
-----2
-----3
-----5
-----8
-----13
-----21
-----34
-----55
-----89
利用for...of循环,可以写出遍历任意对象(object)的方法。原生的 JavaScript 对象没有遍历接口,无法使用for...of循环,通过 Generator 函数为它加上这个接口,就可以用了。
function* objectEntries(obj) {
let propKeys = Reflect.ownKeys(obj);
for (let propKey of propKeys) {
yield [propKey, obj[propKey]];
}
}
let jane = { first: 'Jane', last: 'Doe' };
for (let [key, value] of objectEntries(jane)) {
console.log(`${key}: ${value}`);
}
// first: Jane
// last: Doe
上面代码中,对象jane原生不具备Iterator 接口,无法用for...of遍历。这时,我们通过Generator 函数objectEntries为它加上遍历器接口,就可以用for...of遍历了。加上遍历器接口的另一种写法是,将Generator函数加到对象的Symbol.iterator属性上面。
function* objectEntries() {
let propKeys = Object.keys(this);
for (let propKey of propKeys) {
yield [propKey, this[propKey]];
}
}
let jane = { first: 'Jane', last: 'Doe' };
jane[Symbol.iterator] = objectEntries;
for (let [key, value] of jane) {
console.log(`${key}: ${value}`);
}
// first: Jane
// last: Doe
本文深入探讨ES6的Generator函数,一种异步编程解决方案。详细解释其语法特性,包括yield表达式和遍历器对象的生成,展示了如何利用Generator函数和for...of循环实现迭代和异步控制流。
2348

被折叠的 条评论
为什么被折叠?



