1. jsfor...in循环出来的对象属性顺序到底是什么规律
首先,对于自己的属性排序而言,遵循了特定的规则,即如果属性是数组索引(从0到2^32-2),则按大小排序,其余属性则按照字符串和符号的插入顺序进行排序。
然而,对于for in循环的顺序,则是一个历史遗留问题。最初设计时并未设定具体顺序,直至2019年,委员会根据当时引擎的共同行为进行标准化,顺序为先自己的属性,然后上溯原型链,仅包含可枚举的字符串键。然而,若原型链中包含特殊对象,如代理,或在遍历过程中修改属性或原型链行为,则顺序仍为未定义,因为这些非标准情况在引擎实现上不一致且存在各种奇怪的bug。
总的来说,for in遍历的顺序标准是对实际使用习惯的记录,对于未定义的情况则继续处于未定义状态。
在自己的属性遍历方面,实际的排序与原始意图略有出入。按照最初设计,应该是从0到2^53-1的整数按大小排序。但由于几个主要引擎出于优化目的,将范围限制在了uint32范围内(即数组索引,实际限制为长度减1)。标准委员会试图在标准意图与实现之间保持平衡,但ES6的主导者退休后,引擎厂商代表倾向于避免修改实现,导致目前情况。
原始设计将整数索引视为大小排序,其他属性按插入顺序排列,主要出于对原始对象设计的理解。虽然整数或数组索引都受限于人为设定的上限,但整数索引更为合理,也更不易触及边界。至于性能问题,无论哪种设计,优化策略都是将属性分类存储,本质上无根本差异。厂商曾提出实现复杂度和内存占用增加的理由,但在我看来,这更像是逃避责任的借口。归根结底,设计决策更多地考虑了实现者的便利。
综上所述,JS中for in循环和own keys的排序遵循了特定规则和历史遗留问题,理解这些规则有助于开发者更好地利用语言特性。