object.keys和object.getownpropertynames均返回字符串索引数组,但前者仅含可枚举自有索引,后者包含所有自有索引;因数组索引默认可枚举,故通常结果相同,仅当手动设为不可枚举时才显现差异,且二者均不遍历原型链或length等非索引属性。

两者在处理数组对象时都返回索引字符串组成的数组,但本质逻辑不同:Object.keys只取可枚举的自有索引,Object.getOwnPropertyNames取所有自有索引(包括不可枚举的)——而数组的索引默认全部可枚举,所以日常使用中结果一致。
数组索引默认都是可枚举的
JavaScript 数组的数字索引(如 0、1、2…)在创建时自动设为 enumerable: true。这意味着:
-
Object.keys(arr) 会返回
["0", "1", "2", ...] -
Object.getOwnPropertyNames(arr) 同样返回
["0", "1", "2", ...]
只要没手动修改索引属性的 enumerable 特性,二者输出完全相同。
只有改过索引的枚举性,差异才会显现
你可以用 Object.defineProperty 把某个数组索引设为不可枚举,这时差异就出来了:
-
Object.keys(arr)不再包含那个索引 -
Object.getOwnPropertyNames(arr)依然包含它
例如:
const arr = ["a", "b", "c"];Object.defineProperty(arr, "1", { enumerable: false });
console.log(Object.keys(arr)); // ["0", "2"]
console.log(Object.getOwnPropertyNames(arr)); // ["0", "1", "2"]
它们都不遍历原型链或额外属性
和 for...in 不同,这两个方法只关注数组实例自身的属性:
- 不会输出
length属性(它是不可枚举的,且属于数组内部特性) - 不会输出原型上的方法,比如
push、map - 也不会输出你挂在
Array.prototype上的自定义方法
也就是说,它们真正“看到”的,只是数组元素对应的位置索引(即实际存在的数据槽位)。
注意:索引是字符串,不是数字
无论用哪个方法,返回的都是字符串形式的索引:
-
Object.keys([10, 20])[0] === "0"(类型是 string) - 想转成数字可用
parseInt或一元加号:+"0" === 0
这点对后续排序、计算或作为对象键使用时很关键。











