deprecated ?
中文标题:弃用标记
- 阶段: 未分阶段
- 状态: 不活跃
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入 deprecated; 全局变量或 'deprecated'; 指令,以标准化标记弃用代码,帮助工具和虚拟机进行识别和处理。它提供了灵活的选择,如自动去优化或抛出标志,并讨论了使用 Symbol.deprecated 的 polyfill 策略。提案处于早期阶段,尚无正式规范或委员会决定,正在探索装饰器和内在函数等替代方案。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
弃用的内容
动机
先例
提案
该提案旨在向语言引入一个新的 deprecated; 全局变量,或一个新的 'deprecated'; 指令(pragma),以便通过工具和虚拟机实现,用一种标准的方式轻松识别弃用的代码。
例如:
工具支持:
- 支持
deprecated机制的虚拟机实现可以提供在遇到deprecated代码时抛出的选项(类似于node --throw-deprecation的想法),或者提供一个嵌入器 API,在编译deprecated代码时接收回调,允许 Node.js 等嵌入器能够自定义处理。(类似于 Node.js 的process.on('warning', (warning) => { /* ... */ })API 的想法) - 虚拟机实现可以在任何弃用作用域中自动对代码进行去优化,并在必要时提供忽略
deprecated语句的选项。关键在于,使用弃用代码应该有默认的惩罚,用户需要明确选择退出。(想法类似于:node --no-deprecation) - 调试器、IDE、linter 及相关工具可以提供关于弃用代码使用的可见警告。
指令选项:'deprecated';
或者,deprecated; 可以是一种指令类型的指令:
为了支持伴随代码的“弃用消息”的场景,我们可以使用如下形式:
指令选项具有最少的边界情况,最容易进行 polyfill,并避免可能破坏用户代码的潜在冲突。
同样值得注意的是,指令方法实际上不需要 TC-39 委员会的采取任何行动。VM 和工具提供商可以约定选择支持 'deprecated'; 指令。
Polyfills 和处理歧义
为了使其易于 polyfill 并避免破坏现有代码,这里的 deprecated 实际上可以是一个具有非常特定值的全局属性,而不是一个语言关键字。例如,可以默认定义一个新著名的标准符号 Symbol.deprecated,并将 global.deprecated = Symbol.deprecated。然后,当 VM 或工具在代码中遇到 deprecated;,并且 deprecated 等于 Symbol.deprecated 时,就按上述方式处理。
在较旧的 VM 上,当 deprecated; 被 polyfill 而具有特殊含义时,该语句将是无操作。
VM 在确定是否在运行时进行去优化时应该没有困难,但工具可能会看到一些歧义。例如:
注意:这里预期的 VM 行为是默认情况下自动对代码去优化,并且如果启用了某个标志,则可能抛出。
在这种情况下,工具能做的最好的事情是显示关于歧义使用的警告,并提供一种机制(例如 lint 忽略规则)来退出对该特定情况的检查。
另一个歧义的情况是,如果用户将 Symbol.deprecated 分配给另一个变量会怎样。它会有同样的效果吗?答案是否定的。明确的要求是表达式恰好是 deprecated;(带或不带 ; 是另一个完全不同的论点)。
注意:使用指令选项完全避免这些问题。
我们可以采用类似 import { deprecated } from 'something' 的方法来引入内在,而不是将其设为全局。
具体来说,
这在 VM 行为方面是可以的,但在工具方面会使事情变得更加困难,特别是因为工具必须执行额外的更复杂的分析才能知道 dep; 实际上是什么意思。
即使使用这样的机制,像 linter 这样的工具可能也一直难以可靠地检测到弃用代码的使用。例如,
在这种情况下,工具必须能够可靠地确定 bar() 是否已被 monkey-patched,才能给出任何合理的警告。这就是为什么严格依赖 linter 等工具是不够的。解决这种特定歧义没有银弹。
替代方案:使用装饰器
Decorators 提案提供了解决这个问题的潜在替代方法...
然而,这种方法带有一些重要的局限性:
-
语法不支持向后兼容或不容易进行 polyfill。具体来说,代码需要被转译以移除装饰器才能在旧版本的 Node.js 和旧浏览器上运行,而新的全局和指令方法可以轻松进行 polyfill。
-
在 Node.js 中,我们经常需要在函数内部标记弃用,例如,在某些情况下,只有函数的某些参数组合已被弃用。那么,要让装饰器方法工作,我们需要能够装饰单独的块,例如,
替代方案:deprecated() 内在函数
在 Node.js 中,我们不仅将代码标记为弃用,我们还为弃用关联一个静态标识符和消息,以向用户提供有用的附加信息。虽然这已被证明结果参差不齐,但我们可以在保持上述语义的同时遵循相同的基本模式。
默认的 VM 行为将相同:遇到时自动去优化,如果使用了某个标志则可以选择抛出。提供给函数的消息将提供错误消息文本。
这种方法与提议的方法并不互斥,我们不是定义 global.deprecated === Symbol.deprecated(),而是让 global.deprecated === [内在函数 deprecated()],并具有相同的基本语义。
然而,这可能遇到问题的地方是在前面描述的歧义情况下,用户代码将 deprecated 分配给其他值: