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/object-enumerables.md.
  • 简体中文
  • Object enumerables ?

    中文标题:对象的可枚举属性方法

    提案概览
    提案速览

    该提案引入了 Object.enumerableKeys、Object.enumerableValues 和 Object.enumerableEntries,以枚举继承的可枚举属性,补充现有的 Object.keys/values/entries。它解决了原型链上序列化和迭代的需求,如 Lodash 等库常用。这些方法返回数组,类似于 for.in 循环,且基于提供的类似规范的算法,尚处于早期阶段。

    Note

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

    Object.enumerableKeys / Object.enumerableValues / Object.enumerableEntries

    理由

    遵循 Object.values 和 Object.entries 提案中的 理由,这些方法对于从对象获取键、值和键/值对(规范中称为“条目”)的数组非常有用,以便进行迭代或序列化。

    它们被 Lodash 等库广泛使用。方法名称基于 Lodash 的 _.keysIn_.valuesIn_.forIn 方法,这些方法灵感来自 for…in 和 JS 的 Object.{keys, values, entries}

    返回值类似于当前 Object 中的三重 {keys, values, entries},主要区别在于枚举原型链中的属性,就像 for…in 循环一样。在 Reflect.enumerate 移除后,Object.enumerableKeys 有了额外的动机,这是跟随 [[Enumerate]] 内部方法的移除。

    当前方法与 Reflect.enumeratefor…in 循环一致,因为它只列出可枚举属性的字符串键,忽略任何 symbol 键。

    数组与迭代器

    这些新增是对现有 Object.keysObject.valuesObject.entries 的补充。它们基本上是相同的方法,但包含继承的字符串值键。

    使用场景

    在对象中广泛使用原型链的情况下,序列化自有和继承的条目是有价值的。Lodash 方法的大量使用是一个很好的用例。

    jQuery 的 $.extend$.fn.extend 以及 Underscore/Lodash 的 _.extend/_.assignIn_.defaults 会迭代自有和继承的可枚举属性。在 Lodash 的情况下,keysIn 用于获取要迭代的属性名。它也用于 Underscore 的 _.functions 和 Lodash 的 _.functionsIn

    Object.enumerableValues 的使用可以映射到 values 的使用,后者用于库辅助函数,如 Underscore/Lodash 的 includes(用于检查值是否在对象中)或 sample(从对象中随机获取一个值)。

    Mongoose 这样的 Node.js 数据库包在处理数据对象时使用这些 Lodash 方法。

    Lodash 的 _.toPlainObject 将继承的属性展平为新对象的自有属性。这对于使用 Object.assign 很方便,并且 keysIn 用于实现它。

    示例

    // 给定当前变量:
    var results;
    var iterSuper = {
      foo: 42
    };
    var iter = Object.create( iterSuper );
    iter.bar = 43;

    Object.enumerableKeys( O )

    // 之前
    results = [];
    
    for ( let x in iter ) {
      results.push( x );
    }
    
    results; // [ "foo", "bar" ]
    
    // 之后
    results = Object.enumerableKeys( iter );
    results; // [ "foo", "bar" ](与 for 循环顺序相同)

    Object.enumerableValues( O )

    // 之前
    results = [];
    
    for ( let x in iter ) {
      results.push( iter[ x ] );
    }
    
    results; // [ 42, 43 ]
    
    // 之后
    results = Object.enumerableValues( iter );
    results; // [ 42, 43 ](与 for 循环顺序相同)

    Object.enumerableEntries( O )

    // 之前
    results = [];
    
    for ( let x in iter ) {
      results.push( [ x, iter[ x ] ] );
    }
    
    results; // [ [ "foo", 42 ], [ "bar", 43 ] ]
    
    // 之后
    results = Object.enumerableEntries( iter );
    results; // [ [ "foo", 42 ], [ "bar", 43 ] ](与 for 循环顺序相同)

    规范

    Object.enumerableKeys( O )

    1. obj 为 ? ToObject(O)。
    2. nameList 为 ? EnumerableProperties(obj, "key")。
    3. 返回 CreateArrayFromList(nameList)。

    Object.enumerableValues( O )

    1. obj 为 ? ToObject(O)。
    2. nameList 为 ? EnumerableProperties(obj, "value")。
    3. 返回 CreateArrayFromList(nameList)。

    Object.enumerableEntries( O )

    1. obj 为 ? ToObject(O)。
    2. nameList 为 ? EnumerableProperties(obj, "key+value")。
    3. 返回 CreateArrayFromList(nameList)。

    EnumerableProperties

    当抽象操作 EnumerableProperties 以对象 O 和字符串 kind 调用时,采取以下步骤:

    1. 断言:Type(O) 是对象。
    2. iterator 为 ? EnumerateObjectProperties(obj)。
    3. properties 为一个新的空列表。
    4. 重复
    5. next 为 ? IteratorStep(iterator)。
    6. 如果 nextfalse,返回 properties
    7. nextArg 为 ? IteratorValue(next)。
    8. 如果 kind"key",将 nextArg 追加为 properties 的最后一个元素。
    9. 否则: 1. 令 value 为 ? Get(O, key)。 1. 如果 kind"value",将 value 追加到 properties。 1. 否则:
      1. 断言:kind"key+value"
      2. entry 为 CreateArrayFromList(« key, value »)。
      3. entry 追加到 properties