JavaScript

[EcmaScript] yield* next

2017-01-09  本文已影响14人  何幻

1. iterator和iterable

iterator是一个实现了next方法的对象,
next方法返回一个{value:Anything,done:Boolean}对象。

iterable是一个实现了Symbol.iterator方法的对象,
Symbol.iterator方法方法返回一个iterator

iterator = {
    next: () => ({ value, done })
}

iterable = {
    [Symbol.iterator]: () => iterator
}

2. generator

generator返回的对象,既可以看做是一个iterator,也可以看做是一个iterable

iterator = {

    // iterator
    next: v => ({ value: xxx, done: xxx }),

    // iterable
    [Symbol.iterator]: () => iterator
};

iterator[Symbol.iterator]() === iterator

3. yield与yield*

yield*可以用来yield其他iterable,如果yield*后面不是iterable会报错。

yield* iterable;

4. yield表达式和yield*表达式的值

yield表达式的值,是下一个iter.next的参数值。

let gen = function* () {
  let r = yield 1;
  console.warn(r);    //3
}

let iter = gen();
console.log(iter.next(2));    //{value:1,done:false}
console.log(iter.next(3));    //{value:undefined,done:true}

yield*表达式的值,是yield*后的iterabledonetrue时的value值。

let gen1 = function* () {

  //[{value:1,done:false},{value:2,done:false},{value:3,done:true}]
  let r = yield* gen2();    

  console.warn(r);    //3
}

let gen2 = function* () {
  let x1 = yield 1;
  let x2 = yield 2;
  return 3;
}

let iter = gen1();
console.log(iter.next());    //{value:1,done:false}
console.log(iter.next());    //{value:2,done:false}
console.log(iter.next());    //{value:undefined,done:true} 

5. 使用yeild*串联generator

let gen1 = function* () {
    yield 1;
    yield 2;
}

let gen2 = function* (next) {
    yield 3;
    yield* next;    //yeild* iterable
    yield 4;
}

let gen3 = function* (next) {
    yield 5;
    yield* next;    //yeild* iterable
    yield 6;
}

//将gen1(),gen2(...)用作iterable,将gen3(...)用作iterator
let iter = gen3(gen2(gen1()));

console.log(iter.next());    //{value:5,done:false}
console.log(iter.next());    //{value:3,done:false}
console.log(iter.next());    //{value:1,done:false}
console.log(iter.next());    //{value:2,done:false}
console.log(iter.next());    //{value:4,done:false}
console.log(iter.next());    //{value:6,done:false}
console.log(iter.next());    //{value:undefined,done:true}
console.log(iter.next());    //{value:undefined,done:true}

6. 串联任意多的generator

function compose(gens) {
    return function* (next) {
        if (!next) next = noop();    //next是一个iterable

        let i = gens.length;
        while (i--) {

            //next是一个iterable
            //gens[i]是一个generator,调用后返回一个iterable
            //将上一个next传入gens[i],该gens[i]中就可以yield* next了
            next = gens[i].call(this, next);
        }

        return yield* next;    //yield* iterable
    }
}

function* noop() { }

7. 用例

let gen = compose([gen3, gen2, gen1]);
let iter = gen();

console.log(iter.next());    //{value:5,done:false}
console.log(iter.next());    //{value:3,done:false}
console.log(iter.next());    //{value:1,done:false}
console.log(iter.next());    //{value:2,done:false}
console.log(iter.next());    //{value:4,done:false}
console.log(iter.next());    //{value:6,done:false}
console.log(iter.next());    //{value:undefined,done:true}
console.log(iter.next());    //{value:undefined,done:true}

参考

Github: koajs/compose
iterator和iterable
generator
yield与yield*

上一篇 下一篇

猜你喜欢

热点阅读