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/proposal-extended-numeric-literals.md.
  • 简体中文
  • Extensible numeric literals ?

    中文标题:可扩展数值字面量

    提案概览
    提案速览

    该提案引入了可扩展的数值字面量,允许在数值字面量后添加自定义后缀,以创建用户定义的数值类型或利用特定领域表示法(如 CSS 单位)。它提出了一种语法,通过 with suffix 声明将后缀绑定到一个函数,该函数接收一个包含字面量字符串和数值的对象。

    Note

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

    数值字面量后缀

    状态:已撤回

    champion: Daniel Ehrenberg

    动机

    泛化 BigInt

    JavaScript 包含两种数值类型:NumberBigInt。为了区分字面量语法,BigInt 的书写以 n 结尾,例如 19824359823509831298352352n。对于 BigInt 而言,这是对 JavaScript 语法的一次性更改。

    其他可能添加的数值类型包括:

    • IEEE 754-2008 128 位十进制
    • 任意精度十进制
    • 有理数
    • 复数

    希望这些类型可以内置到语言中 仅由 JavaScript 代码定义,而无需使用转译器/工具。泛化内置语法的一部分是运算符重载;另一部分是自定义数值字面量后缀。

    自定义数值类型示例:

    import { Decimal } from "./my-decimal-package.mjs";
    
    with suffix $ = Decimal.literal;
    (2.1$).plus(3.2$) // ==> 5.3$

    CSS 类型化对象模型

    CSS 类型化对象模型 中,有表示像素、英寸和其他几种单位的长度对象。当前创建此类实例的语法是 CSS.px(10)。使用此提案,语法可以类似 CSS 内部一样,直接写为 10px

    这是另一个可以从运算符重载中受益,但即使没有重载也很有用的案例。

    由于 CSS 内置于 Web 环境中,此示例假定环境在默认外部作用域中提供它。

    示例:

    document.querySelector("#foo").style.fontSize = 3px;

    提议的语法

    数值字面量具有 Number 后跟受限标识符的语法。该标识符必须以一个在有效 NumericLiteral 中永远不会出现的字符开头。

    NumericLiteral ::
      DecimalLiteral
      DecimalLiteral SuffixIdentifier
      NonDecimalIntegerLiteral
      NonDecimalIntegerLiteral SuffixIdentifier
    
    SuffixIdentifier ::
      SuffixIdentifierStart IdentifierPart
    
    SuffixIdentifierStart ::
      UnicodeIDStart but not one of HexDigit or o x O X
      $
    
    LexicalDeclaration :
      LetOrConst BindingList
      SuffixDeclaration
    
    SuffixDeclaration :
      with suffix SuffixIdentifier Initializer

    |NumericLiteral| 和 |SuffixIdentifier| 之间不允许有空白。此限制通过将其作为词法语法(而非句法语法)的一部分(:: 而不是 :)在语法中编码。注意 _ 不是 UnicodeIDStart 的成员。

    对于特定的内置数值后缀(如 n)的早期错误仍然存在,但仅在该后缀未被用户定义的数值字面量后缀遮蔽时触发。非内置的数值字面量后缀可以在其被求值时使用运行时错误。

    作用域

    数值字面量后缀存在于一个平行的词法作用域中。可以通过 SuffixDeclaration 在该作用域中创建条目,形式为 with suffix s = expression。数值字面量中的用法引用当前或外部作用域中的这些后缀之一。

    从模块导入后缀时,使用正常的词法作用域。在导入模块中可以用一行代码在当前作用域中声明它。未来的提案可能允许在后缀命名空间中直接导出/导入,但本提案省略了该功能,因为似乎不值得增加复杂性。

    语义

    用户定义的数值字面量后缀的设计方式类似于模板字面量:它们被调用时传入一个基于调用点的固定对象。该对象有两个自有属性:

    • string:后缀之前的字面量源文本。
    • numberstring 解释为字面量 Number。解析后的形式对于像 CSS Typed OM 这样的用户很重要,因为它需要避免因性能原因而重新解析。

    以下是一个针对假设的 CSS px 字面量后缀的完整可运行 polyfill:

    function pxSuffix({number}) {
      return CSS.px(number)
    }
    
    with suffix px = pxSuffix;
    
    3px;

    最后一行脱糖为:

    let template = Object.freeze({ number: 3, string: "3" });
    pxSuffix(template);

    缓存

    传递给后缀函数的对象会被缓存,这样同一代码的多次执行将使用同一个对象传递给扩展字面量函数。这对于需要昂贵计算来解析的字面量很有用:可以将该对象用作 WeakMap 中的键,将字面量与其预计算值关联起来。

    与最近采用的模板字符串字面量语义(PR)类似,扩展的数值字面量对象按源位置缓存,而不是按数值字面量的内容缓存。

    使用此缓存逻辑,px polyfill 可以优化以避免每次创建新对象:

    const cache = new WeakMap();
    function pxSuffix(obj) {
      if (cache.has(obj)) return cache.get(obj);
      const px = Object.freeze(CSS.px(obj.number));
      cache.set(obj, px);
      return px;
    }

    状态

    此提案在 TC39 中处于 Stage 1。使用独立后缀命名空间的新版本尚未提交给委员会。