我看到一个关于 for...in 语句的迭代顺序的问题,并警告该顺序不能被信任。当前和访问节点的迭代和跟踪是如何在内部完成的,它在 JavaScript 引擎之间有何不同?
2 回答
来自MDN 文档for...in
(强调添加):
以任意顺序迭代对象的可枚举属性。
我确信内部细节因 JavaScript 引擎而异,甚至很可能在任何特定引擎的版本之间。我猜在许多引擎中,它是通过某种哈希表实现来完成的。由于哈希函数会随着哈希表的增长对键进行重新排序,因此属性的相对顺序a
可以b
通过添加新属性来更改c
,而无需更改引擎或任何东西。
似乎Object.keys()
and的实现Object.defineProperties
应该模仿以下行为for...in
:
如果实现为 for-in 语句定义了特定的枚举顺序,则在该算法的第 5 步中必须使用相同的枚举顺序。
所以它们可以作为参考。
操作员还可以使delete
事情复杂化:
未指定枚举属性的机制和顺序(第一个算法中的步骤 6.a,第二个算法中的步骤 7.a)。被枚举对象的属性可能在枚举过程中被删除。如果在枚举期间还没有访问过的属性被删除,那么它就不会被访问。如果在枚举过程中向正在枚举的对象添加了新属性,则不能保证在活动枚举中访问新添加的属性。在任何枚举中不能多次访问属性名称。
可以命名原型链中的冲突:
枚举对象的属性包括递归地枚举其原型的属性、原型的原型等等;但是如果原型的属性被“隐藏”,则不会枚举它,因为原型链中的某些先前对象具有同名的属性。在确定原型对象的属性是否被原型链上的前一个对象遮蔽时,不考虑 [[Enumerable]] 属性的值。
参考