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/year/pending/proposal-do-expressions.md.
  • 简体中文
  • do expressions S1

    中文标题:do 表达式

    提案概览
    提案速览

    do 表达式提案通过允许块语句作为表达式使用,返回最后一条语句的完成值,将面向表达式的编程引入 ECMAScript。它旨在简化当前使用嵌套三元表达式或语句序列的代码,并且在如 JSX 的模板上下文中特别有用。

    Note

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

    ECMAScript 提案:do 表达式

    本提案有 初步规范文本

    状态

    本提案处于 TC39 流程阶段 1

    动机

    • 面向表达式的编程是函数式编程的重大进步之一
    • 表达式像乐高积木一样拼接,使得小规模编程体验更加灵活

    示例

    以面向表达式的风格编写,尽可能局部地限定变量作用域:

    let x = do {
      let tmp = f();
      tmp * tmp + 1
    };

    将条件语句用作表达式,而不是笨拙的嵌套三元表达式:

    let x = do {
      if (foo()) { f() }
      else if (bar()) { g() }
      else { h() }
    };

    特别适合像 JSX 这样的模板语言:

    return (
      <nav>
        <Home />
        {
          do {
            if (loggedIn) {
              <LogoutButton />
            } else {
              <LoginButton />
            }
          }
        }
      </nav>
    )

    限制

    由于可能造成混淆,你不能以声明、没有 elseif 或循环(即使嵌套在其他语句中)来结束 do 表达式。例如,以下都是早期错误:

    (do {
      let x = 1;
    });
    (do {
      function f() {}
    });
    (do {
      while (cond) {
        // 做某事
      }
    });
    (do {
      if (condition) {
        while (inner) {
          // 做某事
        }
      } else {
        42;
      }
    });
    (do {
      label: {
        let x = 1;
        break label;
      }
    });
    (do {
      if (foo) {
        bar
      }
    });

    更正式地说,StatementList 的完成值不能依赖于循环或声明的完成值。详见提议规范中的 EndsInIterationOrDeclaration。

    对声明的限制尤其令人遗憾。这源于声明的完成值具有 ~empty~,意味着 do { 'before'; let x = 'after'; } 将求值为 before。我希望追求普遍改变声明的完成值,但这会影响依赖 eval 的现有代码。

    边界情况

    var 声明

    允许 var 声明(除了作为最后一条语句),其绑定提升到包含函数的词法作用域。例外:当 do 出现在参数表达式中时,var 声明是早期错误。

    do

    允许 do {},它等同于 void 0

    await/yield

    使用 awaityield 的能力继承自封闭函数的上下文,如同在任何其他表达式中一样。

    throw

    正常工作。做你期望的事情。

    break/continue/return

    在适当的上下文中允许使用:当 do 在函数内时允许 return,当在循环或 switch 分支内时允许 break 等等。这允许你编写如下代码:

    function getUserId(blob) {
      let obj = do {
        try {
          JSON.parse(blob)
        } catch {
          return null; // 从函数返回
        }
      };
      return obj?.userId;
    }
    异常情况

    由于可能造成混淆,无论在循环内部是否有另一层循环,在循环头部都不允许使用未标记的 breakcontinue

    甚至在函数参数列表中允许 return,例如 function f(x = do { return null; }) {}。在类体的计算属性名中不允许。

    do-while 的冲突

    在语句合法的上下文中禁止使用 do 表达式。在这种上下文中,你可以使用普通块或将 do 表达式用括号括起来。

    B.3.3 函数提升

    宽松模式的函数提升不允许穿过 do 表达式。