For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/stage/2/proposal-function.sent.md.
  • 简体中文
  • function.sent metaproperty S2

    中文标题:function.sent 元属性

    提案概览
    提案速览

    function.sent 元属性提案解决了生成器内部无法访问第一次 next 参数的问题,因为第一次调用不对应于 yield。它引入了 function.sent 来提供最近一次 next 调用传递的值,包括初始调用。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    生成器 function.sent 元属性

    状态

    阶段:
    2
    作者:
    Allen Wirfs-Brock (2015年5月13日)
    倡导者:
    何世君 (@hax)

    问题

    当在生成器对象上调用 next 方法时,作为第一个参数传递给 next 的值被“发送”给生成器对象,并在生成器函数体内作为最近一次挂起生成器函数的 yield 表达式的值可用。这支持生成器对象与其消费者之间的双向通信。

    然而,生成器的消费者调用来启动生成器对象的第一个 next 不对应于生成器函数体内的任何 yield。相反,第一个 next 只是导致生成器函数体从顶部开始执行。

    因为第一个 next 调用不对应于生成器函数体内的 yield,所以目前代码无法访问初始的 next 参数。例如:

    function *adder(total=0) {
       let increment=1;
       while (true) {
           switch (request = yield total += increment) {
              case undefined: break;
              case "done": return total;
              default: increment = Number(request);
           }
       }
    }
    
    let tally = adder();
    tally.next(0.1); // 参数将被忽略
    tally.next(0.1);
    tally.next(0.1);
    let last=tally.next("done");
    console.log(last.value);  //1.2 而不是 0.3

    在上面的例子中,next 方法的参数通常提供要加到运行总计中的值。但第一次 next 提供的增量值被忽略了。

    本提案提供了一种访问 next 参数的替代方式,这种方式在生成器的 next 方法的第一次及所有后续调用中都有效。

    提案

    一个新的元属性:function.sent

    值与上下文

    在生成器函数体内,function.sent 的值是最近一次恢复生成器执行的 next 方法传递给生成器的值。特别是,在首次评估 yield 运算符之前引用 function.sent 会返回启动 GeneratorBody 评估的 next 调用传递的参数值。

    function.sent 可以出现在任何 YieldExpress 合法的地方。在 GeneratorBody 之外引用 function.sent 是语法错误。

    使用示例

    以下是使用 function.sent 重写上述示例的方式:

    function *adder(total=0) {
       let increment=1;
       do {
           switch (request = function.sent){
              case undefined: break;
              case "done": return total;
              default: increment = Number(request);
           }
           yield total += increment;
       } while (true)
    }
    
    let tally = adder();
    tally.next(0.1); // 参数不再被忽略
    tally.next(0.1);
    tally.next(0.1);
    let last=tally.next("done");
    console.log(last.value);  //0.3

    规范更新

    以下是对 ECMAScript 2015 语言规范的增量修改

    8.3 执行上下文

    表 24中添加以下行:

    组件描述
    LastYieldValue最近评估的 YieldExpression 的值

    12.3 左值表达式

    语法

    MemberExpression[Yield]  :
                ...
                MetaProperty[?Yield]
                ...

    MetaProperty[Yield]  :
                NewTarget
                 [+Yield] FunctionSent

    14.4 生成器函数定义

    语法

    FunctionSent  :
                function . sent

    14.4.14 求值

    FunctionSent : function . sent
        1.  断言:正在运行的执行上下文是生成器上下文。
        2.  令 genContext 为正在运行的执行上下文。
        3.  返回 genContext 的 LastYieldValue 组件的值。

    25.3.3.1 GeneratorStart(generator, generatorBody)

    在 ES6 算法的第 3 行和第 4 行之间添加以下步骤:

        3.5.  将 genContext 的 LastYieldValue 组件设置为 undefined

    25.3.3.3 GeneratorResume(generator, value)

    在 ES6 算法的第 8 行和第 9 行之间添加以下步骤:

        8.5.  将 genContext 的 LastYieldValue 组件设置为 value

    25.3.3.5 GeneratorYield(iterNextObj)

    在 ES6 算法的第 5 行和第 6 行之间添加以下步骤:

        5.5.  将 genContext 的 LastYieldValue 组件设置为 undefined