【问题标题】:In JavaScript is Object.keys().forEach() less memory efficient than a simple for...in loop?在 JavaScript 中,Object.keys().forEach() 的内存效率是否比简单的 for...in 循环低?
【发布时间】:2015-04-22 19:48:46
【问题描述】:

假设您有一个非常大的 JS 对象,包含数百万个键/值对,您需要对它们进行迭代。

This jsPerf example 显示了主要的实现方式,并概述了速度差异。

我想知道的是:与其他循环方法相比,使用Object.keys() 对内存的影响会有所不同,因为它需要首先创建包含所有对象键的“索引”数组?

源代码中是否有任何优化可以防止这种情况发生?

【问题讨论】:

    标签: javascript loops object ecmascript-5


    【解决方案1】:

    问题在于对象键将 for..in 与 hasOwn 属性结合在一起,因此根据您的最终目标,它们可以是独占的或可互换的。至于你自己看到的基准,这一切都归结为引擎的实现。查看此答案了解更多信息

    for-in vs Object.key forEach without inherited properties

    【讨论】:

    • 你好大研,你怎么知道Object.keys()的实现细节,你看过源码吗?我想如果它在内部使用for...inhasOwnProperty(),那么不会有这么大的性能差异。
    • 不,我还没有看到每个 JS 引擎的源代码,但众所周知,并非所有浏览器都以相同的方式构建其 JS 解释器。所以对某些人来说可能正确的事情可能对其他人来说不是。
    【解决方案2】:

    您正在寻找的是对对象或数组属性的延迟迭代。这在 ES5 中是不可能的(因此在许多实现中是不可能的,例如 node.js)。我们最终会得到这个。

    内存方面,for ... inObject.keys.forEach 都会将整个属性集加载到内存中。每个 JS 引擎使用多少实际内存可能会有很大差异。您应该始终在不同的场景下测试您的代码,并使用多个引擎来确定哪种引擎最适合您的应用程序。

    【讨论】:

    • 谢谢伊万!是否有任何关于这两种方法如何在内存方面执行的数据?如果我理解正确,即使两者都将整个集合加载到内存中,Object.keys() 仍然需要复制对象键占用的空间,以便返回包含它们的数组,对吗?
    • 不是这样的,因为 Object.keys 是一个本地方法。因此,对于初学者来说,它比其他方法快得多(它在性能方面更加优化)。至于内存消耗,这取决于引擎实现(它们中的大多数使用 hashMap 来更快地访问和减少内存)。另外,请注意,使用 for...inhasOwnProperty() 仅匹配非继承属性会为每个键创建一个函数,从而增加内存消耗并大大降低性能。
    • 嗨 Iván,对不起,本地或非本地,Object.keys() 仍然返回一个数组,并且该数组需要存储在某个地方。对象键是字符串,因此按值传递(如果您修改返回数组中的元素,则不会触及原始对象键)。据我了解,这意味着调用该方法时对象键的内存使用量将重复。
    • 你是对的,因为你得到了重复的键并使用了两倍的空间。我的意思是所有迭代器都会导致这种数据重复。我的意思是 Object.keys 往往会导致更少的内存使用,因为它是一种本机方法,因此,创建键数组是一个比其他方法更优化的过程。如果我没有正确解释自己,我深表歉意。
    • 当您说“所有迭代器导致此数据重复”时,您究竟是什么意思?例如,“for...in”如何迭代对象键?你知道这是如何在源代码中实现的吗?干杯
    猜你喜欢
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 2017-01-05
    • 2017-10-02
    • 2018-01-14
    • 2016-09-02
    相关资源
    最近更新 更多