JavaScript中,Object.keys().forEach()比简单的for...in循环更节省内存吗?

3
假设你有一个非常大的JS对象,包含数百万个键/值对,并且你需要迭代它们。 这个 jsPerf示例展示了主要的方法,并概述了它们之间的速度差异。 我想知道的是:与其他循环方法相比,使用Object.keys()是否会对内存产生不同的影响,因为它需要先创建包含所有对象键的“索引”数组? 源代码中是否有任何优化可以防止这种情况发生?
2个回答

3
您需要的是针对对象或数组属性的懒惰迭代。在ES5中这是不可能的(因此在许多实现中也不可能,例如node.js)。我们最终会解决这个问题。
就内存而言,无论是使用for ... in还是Object.keys.forEach,都会将整个属性集加载到内存中。每个JS引擎实际使用的内存量可以有很大差异。您应该始终在不同的场景和使用几个引擎的情况下测试您的代码,以确定哪个在您的应用程序上运行得最好。

1
谢谢Iván!这两种方法在内存方面的表现是否已经有可用的数据?如果我理解正确,即使两者都将整个集合加载到内存中,Object.keys()仍然需要复制对象键占用的空间,以便返回包含它们的数组,对吗? - Pensierinmusica
1
并不是这样的,因为Object.keys是一种本地方法。因此,首先,它比其他方法要快得多(在性能方面进行了优化)。至于内存消耗,这取决于引擎实现(大多数引擎使用哈希映射表以实现更快的访问和内存减少)。此外,请注意,使用for...inhasOwnProperty()匹配仅非继承属性会为每个键创建一个函数,从而增加内存消耗并大大降低性能。 - imelgrat
1
嗨,伊万,抱歉,无论是母语还是非母语,Object.keys()仍然返回一个数组,并且该数组需要存储在某个地方。对象键是字符串,因此按值传递(如果您修改返回的数组中的元素,则不会触及原始对象键)。据我理解,这意味着在调用该方法时,对象键的内存使用将被复制。 - Pensierinmusica
您是否有这两种方法实现源代码的参考? - Pensierinmusica
不,这只是根据我的经验说的(使用 Chrome 的 DevTools 监控内存使用和性能),以及在研究过程中查阅的一些页面。我不使用 C/C++,所以没有查找代码。 - imelgrat
显示剩余4条评论

0

问题在于Object Keys将for..in与hasOwn属性结合起来,因此根据您的最终目标,它们可以是互斥的或可互换的。至于您看到的基准测试,这完全取决于引擎实现。请查看此答案以获取更多信息

for-in vs Object.key forEach without inherited properties


嗨Dayan,你是怎么知道Object.keys()的实现细节的?你看过源代码吗?我猜想如果内部使用for...inhasOwnProperty(),那么性能差异不会那么大。 - Pensierinmusica
1
我还没有看过每个JS引擎的源代码,但已经是一个众所周知的事实,不是所有浏览器都以相同的方式构建其JS解释器。因此,对于某些浏览器可能是真实的,而对于其他浏览器则可能不是。 - Dayan Moreno Leon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接