object.getownpropertynames只获取对象自身属性名(含不可枚举属性),不涉及原型链;要获取整条原型链上所有自有属性名需手动遍历原型并用set去重。

Object.getOwnPropertyNames 只能获取对象**自身**的属性名(包括不可枚举属性),但它**完全不涉及原型链**——它不会返回原型上的任何属性,无论是否可枚举。
它只查“自己身上”的属性,不看原型
这个方法的设计目标就是严格区分“自有属性”和“继承属性”。即使原型上有个不可枚举的属性,Object.getOwnPropertyNames(obj) 也绝不会把它列出来。
例如:
const parent = {};
Object.defineProperty(parent, 'hidden', {
value: 'from prototype',
enumerable: false
});
const child = Object.create(parent);
child.normal = 'own';
Object.defineProperty(child, 'ownHidden', {
value: 'only here',
enumerable: false
});
console.log(Object.getOwnPropertyNames(child));
// → ['normal', 'ownHidden'] —— 只有 child 自己定义的两个属性
// → 没有 'hidden',哪怕它在原型上且不可枚举
想同时拿到自身 + 原型链上的所有自有属性名?得手动遍历
JavaScript 没有内置方法一步到位获取整条原型链上所有自有属性名。你需要配合 Object.getPrototypeOf 逐级向上收集,并用 Set 去重(避免重复属性名):
- 从目标对象开始,调用
Object.getOwnPropertyNames获取当前层自有属性名 - 用
Object.getPrototypeOf拿到它的原型 - 对原型重复上述操作,直到原型为
null - 用
Set合并所有结果,保证每个属性名只出现一次
function getAllPropertyNames(obj) {
const names = new Set();
let current = obj;
while (current !== null) {
Object.getOwnPropertyNames(current).forEach(name => names.add(name));
current = Object.getPrototypeOf(current);
}
return Array.from(names);
}
console.log(getAllPropertyNames(child));
// → ['normal', 'ownHidden', 'hidden'](如果 parent 是直接原型)
注意:不可枚举 ≠ 不可访问,也不影响 getOwnPropertyNames
不可枚举属性只是不会出现在 for...in 或 Object.keys() 中,但它们仍是对象自身的属性,Object.getOwnPropertyNames 照样能捕获——只要它是当前对象“自己定义的”。
-
Object.keys(obj):只返回自身可枚举属性 -
Object.getOwnPropertyNames(obj):返回自身所有属性(可枚举 + 不可枚举) -
Reflect.ownKeys(obj):同getOwnPropertyNames,但还包含 Symbol 属性
小结:别指望 getOwnPropertyNames 查原型
它名字里的 “Own” 就是关键——只认“亲生的”,不认“长辈传的”。要查原型链,必须主动遍历;要包含 Symbol,就该换用 Reflect.ownKeys。理解这点,就不会误用或期待错误行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











