【问题标题】:Generator yield value difference发电机良率差
【发布时间】:2014-05-08 12:15:46
【问题描述】:

假设我们有以下生成器函数:

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

我们还有两个生成器,它们产生上面的生成器:

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

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

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

【问题讨论】:

    标签: javascript ecmascript-harmony yield-keyword


    【解决方案1】:

    你的代码效果是这样的:

    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
    

    【讨论】:

    • 我觉得* i()的定义应该是{ yield 6; yield* h(); yield 7 }
    【解决方案2】:

    引用:

    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(); 如果我错了请纠正我(尽管我完全怀疑会有一些极端情况,例如任何例外。)

    【讨论】:

      猜你喜欢
      • 2015-10-24
      • 1970-01-01
      • 2011-03-17
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多