ECMAScript 6学习笔记之----Generator函数和异步应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Pengjx2014/article/details/89435361

基本概念

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方法,就会返回一个有着valuedone两个属性的对象。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

猜你喜欢

转载自blog.csdn.net/Pengjx2014/article/details/89435361
今日推荐