Object.keys()仅返回对象自身可枚举的字符串属性名,Object.getOwnPropertyNames()返回所有字符串属性名(含不可枚举),二者均不包含Symbol属性且不遍历原型链。

Object.keys() 只返回对象自身**可枚举(enumerable)的字符串属性名**;Object.getOwnPropertyNames() 返回对象自身**所有字符串属性名(包括不可枚举的)**,但不包含 Symbol 属性。
只看“可枚举性”这一关键差异
JavaScript 中每个属性都有一个 enumerable 描述符,默认为 true。只有当它为 true 时,该属性才会被 Object.keys()、for...in 和 JSON.stringify() 等识别。
-
Object.keys(obj):过滤掉enumerable: false的属性 -
Object.getOwnPropertyNames(obj):不管enumerable是真是假,只要属性名是字符串就返回
两者都不返回 Symbol 类型的属性名
如果对象有 Symbol 属性(比如 obj[Symbol('id')] = 123),无论用 Object.keys() 还是 Object.getOwnPropertyNames() 都拿不到它。
- 要获取 Symbol 属性,得用
Object.getOwnPropertySymbols(obj) - 想拿到全部属性名(字符串 + Symbol),可以合并:
[...Object.getOwnPropertyNames(obj), ...Object.getOwnPropertySymbols(obj)]
都只查“自身属性”,不查原型链
这两个方法都不会向上遍历原型链 —— 它们只关心对象自己直接拥有的属性。
- 比如
{}.toString来自Object.prototype,所以不会出现在Object.keys({})或Object.getOwnPropertyNames({})结果中 - 若想包含原型链上的可枚举属性,需手动遍历(如用
for...in),但要注意用hasOwnProperty过滤
实际例子一眼看懂
运行这段代码:
const obj = { a: 1 };
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
Object.defineProperty(obj, 'c', { value: 3, enumerable: true });
console.log(Object.keys(obj)); // ['a', 'c']
console.log(Object.getOwnPropertyNames(obj)); // ['a', 'b', 'c']
这里 b 被设为不可枚举,所以 keys 忽略它,而 getOwnPropertyNames 保留它。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











