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/4/proposal-for-in-order.md.
  • 简体中文
  • for-in mechanics S4

    中文标题:for-in 机制

    提案概览
    提案速览

    该提案旨在规范 for-in 循环的枚举顺序,此前在 ECMA-262 中几乎完全未指定。它定义了一组引擎已达成一致的保守互操作语义,涵盖常见情况,不包括外来对象或迭代期间的修改。

    Note

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

    本提案已被接受并合并到主规范。本仓库仅保留用于历史参考。

    规范 for-in 枚举顺序

    (部分地。)

    ECMA-262 将 for (a in b) ... 的顺序几乎完全未指定,但实际引擎在至少某些情况下倾向于保持一致。此外,多年来实现者观察到,任何想在网络上运行代码的人都需要遵循一些规范未包含的约束。

    这是一个阶段4(已完成)提案,旨在开始解决这个问题。

    背景

    历史上,试图就 for-in 顺序的完整规范达成共识的努力多次失败,部分原因是所有引擎都有自己独特的实现,这些实现是大量工作的结果,并且它们并不真正想重新审视。

    参见 exploration 目录,了解在成为具体提案之前的背景和测试用例。

    对互操作语义的保守低估

    这个互操作语义列表中,我们可以得出一个保守的、对引擎已经一致情况的低估,我相信这涵盖了最常见的情况。具体来说:

    • 被迭代的对象或其原型链中的任何对象都不是代理、类型化数组、模块命名空间对象或宿主外来对象。
    • 对象或其原型链中的任何对象在迭代期间都没有改变其原型。
    • 对象或其原型链中的任何对象在迭代期间都没有删除属性。
    • 对象原型链中没有任何属性在迭代期间被添加。
    • 对象或其原型链中的任何属性的可枚举性在迭代期间都没有改变。
    • 没有非可枚举属性遮蔽可枚举属性。

    除最后一条外,其余都相当容易用散文形式说明;最后一条稍微困难一些。据我所知,JavaScriptCore 是唯一一个在这种情况下会输出内容的引擎,因为这个长期存在的bug,所以我希望这一点可以被丢弃。

    影响

    有多种API使得属性枚举顺序可观察。for-in 是最复杂的,因为它独特地也枚举来自原型链的属性。剩余的API可以分为:使用与 for-in 相同的顺序(针对自有属性)的API,这些受此提案影响;以及使用与 Reflect.ownKeys 相同的顺序的API,这些不受影响。

    for-in 顺序影响的API

    以下API使用 EnumerableOwnPropertyNames,它要求其结果“按照与调用 EnumerateObjectProperties 内部方法(使用[相关对象])时返回的迭代器所产生的相同相对顺序”排列。EnumerateObjectPropertiesfor-in 使用的规范内部方法,也是本提案旨在改进的部分。

    other-effects 目录包含测试,演示了这些API如何被观察的简单示例。所有主流引擎在这些情况下已经达成一致。

    因为 JSON.parse 产生的所有对象都在互操作语义范围内,本提案之后将完全指定其行为。其他API可以传入外来参数,因此不会完全指定。

    Reflect.ownKeys 顺序影响的API

    以下API直接调用 [[OwnPropertyKeys]] 内部方法,其行为已完全指定,因此不受本提案影响。

    规范文本

    参见候选规范文本。这尚未捕获上面提到的“没有非可枚举属性遮蔽可枚举属性”的约束,因为我难以想出如何表达它。