现代 javascript 引擎对对象自有属性枚举顺序严格遵循 es2015 规范:数字键按数值升序排最前,字符串键按插入顺序排列,symbol 键在最后并保持插入顺序;object.keys()、for...in 等遍历方法依此规则产出有序结果,但对象本身无固有顺序。

现代 JavaScript 引擎(V8、SpiderMonkey、JavaScriptCore)对对象自有属性的枚举顺序已高度统一,并严格遵循 ES2015 规范,但这种“顺序”不是对象本身的固有特性,而是遍历方法在执行时按规则整理出的结果。
数字键按数值升序排最前
所有能被解析为有效无符号 32 位整数的字符串键(如 "0"、"42"、"999"),无论定义顺序如何,都会被优先提取并按数值大小升序排列。例如:
-
{"10": "a", "2": "b", "1": "c"}→Object.keys()返回["1", "2", "10"] - "-1"、"1.5"、"01" 不属于整数键,归入字符串键类别
字符串键按插入顺序保留
非整数形式的字符串键(如 "name"、"_id"、"01")在自有可枚举属性中,按添加时的顺序排列。这个行为在 Chrome、Firefox、Safari 的当前版本中完全一致。
- 注意:仅限自有属性;原型链上的字符串键不参与此排序逻辑
- 不可枚举属性(如通过
Object.defineProperty设置enumerable: false)不会出现在Object.keys()或for...in中
Symbol 键总在最后,且按插入顺序
所有 Symbol 类型的键统一排在字符串键之后,并彼此之间保持插入顺序:
const s1 = Symbol('a'); const s2 = Symbol('b'); const obj = {x: 1, [s2]: 2, y: 3, [s1]: 4};-
Reflect.ownKeys(obj)返回["x", "y", Symbol(a), Symbol(b)] -
Object.keys()和for...in完全忽略 Symbol 键
哪些操作会破坏或重建顺序
拷贝或转换过程可能改变原始插入顺序的表观结果:
-
Object.assign({}, obj)和展开运算符{...obj}按Object.keys(obj)顺序赋值,结果顺序与Object.keys()一致 -
JSON.parse(JSON.stringify(obj))丢失 Symbol、函数、undefined 等,且所有键转为字符串,数字键仍按数值升序重排 -
for...in在现代引擎中对自有可枚举字符串键的顺序与Object.keys()一致,但若未过滤原型属性,混入的原型键顺序不可控
不复杂但容易忽略:对象本身没有“顺序”,只有遍历方法按规范产出有序结果。真要依赖顺序,就用 Map —— 它从设计上就保证插入顺序,且不受键类型影响。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











