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/2019/proposal-object-from-entries.md.
  • 简体中文
  • Object.fromEntries S4

    提案概览
    提案速览

    该提案引入了 Object.fromEntries,这是一个静态方法,将可迭代的键值对转换为对象,作为 Object.entries 的逆操作。它解决了轻松将 Map 或键值对数组等集合转换为普通对象而无需手动 reduce 循环的需求。

    Note

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

    Object.fromEntries

    此仓库现已归档,因为该提案已达到第 4 阶段。

    关于在 ECMAScript 中新增静态方法 Object.fromEntries 的提案,用于将键值对列表转换为对象。

    该提案最初由 Darien Maillet Valentine 撰写,并由 Jordan HarbandKevin Gibbons 负责推进。

    提案

    Object.fromEntries 被提议用来执行与 Object.entries 相反的操作:它接受一个可迭代的键值对,并返回一个新对象,其自身键和对应值由这些键值对给出。

    obj = Object.fromEntries([['a', 0], ['b', 1]]); // { a: 0, b: 1 }

    详见 DETAILS.md

    理由

    将存储在各种结构(数组、映射等)中的数据从一种形式转换为另一种形式是很常见的。当所涉及的数据结构都是可迭代时,这通常很简单:

    map = new Map().set('foo', true).set('bar', false);
    arr = Array.from(map);
    set = new Set(map.values());

    Map 的可迭代条目采用键值对的形式。这与 Object.entries 返回的键值对非常契合,因此你可以相当有表现力地将对象转换为 Map

    obj = { foo: true, bar: false };
    map = new Map(Object.entries(obj));

    然而,不存在 Object.entries 的逆操作来从键值对构造对象,因此通常需要编写辅助函数或内联归约:

    obj = Array.from(map).reduce((acc, [ key, val ]) => Object.assign(acc, { [key]: val }), {});

    这可以用多种不同的方式编写,并且可能会增加噪音,因为它可能不会明显与执行它的函数的外部目的相关。

    何时有用?

    Object.fromEntries 并不暗示偏好普通对象而非 Map

    如果你有一个具有任意键集合的集合,即使它们是字符串,特别是如果你打算随着时间的推移添加/删除成员,Map 数据可能比对象属性更合适。属性非常适合描述接口或固定形状的模型,但不适合建模任意哈希,而 Map 旨在更好地服务于这种情况。

    我们并不总是能选择模型。这正是 fromEntries 旨在帮助解决的事情之一。认识到某些数据是任意集合,人们可能更喜欢使用 Map 来建模。但后来这些数据可能需要传递给一个契约期望将其建模为普通对象的 API(想想查询参数、请求头等):externalAPI(Object.fromEntries(myMap))

    来自或必须可序列化为 JSON 的数据通常使用属性来建模任意集合。反映条目的元编程是另一种场景,我们可能会操作或过滤条目,然后希望将它们转换回对象——例如,在处理适合传递给 Object.defineProperties 的对象时。再举一个例子,尽管不是每个人都同意这是否是一个好主意,如果作者认为它们能提升 API 的人机工程学,也可以特意选择涉及任意键对象的契约。

    示例

    对象到对象的属性转换

    这允许轻松使用熟悉的数组操作方法转换对象:

    obj = { abc: 1, def: 2, ghij: 3 };
    res = Object.fromEntries(
      Object.entries(obj)
      .filter(([ key, val ]) => key.length === 3)
      .map(([ key, val ]) => [ key, val * 2 ])
    );
    
    // res 为 { 'abc': 2, 'def': 4 }

    从现有集合创建对象

    一个字符串键的 Map 可以转换为对象,就如同对象已经可以转换为 Map 一样:

    map = new Map([ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]);
    obj = Object.fromEntries(map);
    
    // 比较现有功能:new Map(Object.entries(obj))

    对于其他类似 Map 的对象,这种转换可能也很简单:

    query = Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'));

    对于其他集合,中间转换可以使集合达到所需形式:

    arr = [ { name: 'Alice', age: 40 }, { name: 'Bob', age: 36 } ];
    obj = Object.fromEntries(arr.map(({ name, age }) => [ name, age ]));

    先前的工作

    Lodash

    Underscore 和 Lodash 提供了 _.fromPairs 函数,该函数从键值对列表构造一个对象。

    Python

    在 Python 中,dict 可以用 键值元组数组 初始化:

    dict([('two', 2), ('one', 1), ('three', 3)])