Object.keys只返回对象自身的可枚举属性,不包含原型链上的任何属性;它通过设计限定为own properties且enumerable为true,与for...in(含原型)、Object.getOwnPropertyNames(含不可枚举)等方法行为不同。

Object.keys 本身就已经只返回对象**自身**的可枚举属性,**不会包含原型链上的任何属性**——无论它们是否可枚举。
所以你不需要、也无法用 Object.keys “过滤掉”原型上的属性,因为它压根就不会获取它们。
为什么 Object.keys 不会遍历原型链?
这是它的设计行为:
-
只检查对象自身的属性(own properties),不访问
__proto__或Object.getPrototypeOf()链上的属性; - 只返回 可枚举(enumerable: true) 的自有属性键名;
- 不关心原型上有没有同名属性,哪怕原型上有且可枚举,也完全忽略。
对比:哪些方法会读取原型链上的可枚举属性?
如果你看到“原型上的属性被列出来了”,那一定不是 Object.keys 干的,而是用了这些方法:
立即学习“Java免费学习笔记(深入)”;
-
for...in:遍历自身 + 原型链上所有可枚举属性; -
Object.getOwnPropertyNames():返回自身所有属性(含不可枚举),但依然不包含原型链; -
Reflect.ownKeys():类似getOwnPropertyNames,返回自身所有键(包括 Symbol),也不查原型。
想确认某个属性是不是“来自原型”?
可以用 Object.prototype.hasOwnProperty.call(obj, key) 判断:
const parent = { a: 1 };
const child = Object.create(parent);
child.b = 2;
console.log(Object.keys(child)); // ['b'] → 只有自身的
console.log('a' in child); // true → 原型上有
console.log(child.hasOwnProperty('a')); // false
console.log(child.hasOwnProperty('b')); // true
如果真想获取“自身 + 原型链上所有可枚举属性”?
那就得手动遍历原型链,比如:
function getAllEnumerableKeys(obj) {
const keys = [];
for (let o = obj; o !== null; o = Object.getPrototypeOf(o)) {
keys.push(...Object.keys(o));
}
return [...new Set(keys)]; // 去重(避免子类覆盖父类同名属性重复)
}
但注意:这通常不是常见需求,多数场景下 Object.keys 的默认行为正是你想要的“干净的自有属性列表”。


















