发电机产量值差异

时间:2014-03-28 20:48:42

标签: javascript ecmascript-harmony yield-keyword

我们说我们有以下生成器功能:

var gen1 = function * (){
  yield 1;
};

我们还有两台发电机产生以上发电机:

var gen2 = function * () {
    yield gen1;
};

var gen3 = function * () {
    yield *gen1;
};

有人知道yield gen1 yield *gen1之间的区别。 *对生成器做了什么?

2 个答案:

答案 0 :(得分:2)

您的代码的效果如下:

for (let x of gen1()) console.log(x)  // "1"
for (let x of gen2()) console.log(x)  // "function* gen1() { yield 1; }"
for (let x of gen3()) console.log(x)  // throws TypeError

你可能意味着:

var gen2 = function* () {
  yield gen1();
};

var gen3 = function* () {
  yield* gen1();
};

在这种情况下,你得到:

for (let x of gen2()) console.log(x)  // "[object Object]"
for (let x of gen3()) console.log(x)  // "1"

也就是说,普通yield只返回操作数表达式求值的任何内容(在gen2的情况下,是一个未使用的迭代器对象)。另一方面,yield* 委托到另一个迭代器。它将产生迭代器产生的任何东西,直到它耗尽为止。更具体地说:

function* g() { yield 1; yield 2; yield 3 }
function* h() { yield 4; yield* g(); yield 5 }
function* i() { yield 6; yield* h(); yield 7 }

for (let x of i()) console.log(x)  // 6, 4, 1, 2, 3, 5, 7

答案 1 :(得分:1)


QUOTE:

yield*运算符委托给另一台生成器。这为组合生成器提供了便利的机制。

表达式yield* <<expr>>相当于:

let (g = <<expr>>) {
    let received = void 0, send = true, result = void 0;
    try {
        while (true) {
            let next = send ? g.send(received) : g.throw(received);
            try {
                received = yield next;
                send = true;
            } catch (e) {
                received = e;
                send = false;
            }
        }
    } catch (e) {
        if (!isStopIteration(e))
            throw e;
        result = e.value;
    } finally {
        try { g.close(); } catch (ignored) { }
    }
    result
}

这类似于生成器上的for-in循环,除了它将通过外部生成器的throw方法抛出的异常传播到委托生成器中。


来源: http://wiki.ecmascript.org/doku.php?id=harmony:generators#delegating_yield


我没有花太多时间来完全理解它,但是yield* gen;似乎与yield gen();相似如果我错了就纠正我(虽然我完全怀疑会有一些角落案例,例如任何例外情况。)