object.getownpropertynames 与原型链无关,它只返回对象自身定义的字符串属性名(含不可枚举属性),不访问原型链;需判断属性来源时应使用 hasownproperty 或 in 操作符配合检查。

Object.getOwnPropertyNames 本身不依赖也不需要配合原型链——它天然避开原型链,只查对象自身。所谓“配合”,其实是理解二者关系后,避免误用或误解。
Object.getOwnPropertyNames 与原型链无关
这个方法的设计目标就是隔离原型链:
- 它只返回目标对象自身定义的字符串属性名(含不可枚举的)
- 不会访问
obj.__proto__,也不会向上查找Object.prototype、Array.prototype等任何原型上的属性 - 即使原型上有同名方法(如
toString),只要没被显式定义在实例上,就不会出现在结果里
例如:
const arr = [1, 2]; console.log(Object.getOwnPropertyNames(arr)); // ['0', '1', 'length'] // 没有 push、map、join —— 它们都在 Array.prototype 上
需要“处理原型链”的场景其实不存在
你不需要用 getOwnPropertyNames 去“过滤原型干扰”,因为它根本不会拿到原型的东西。
常见误解是以为它会混入 constructor 或 __proto__,但:
-
constructor只有在实例自身被手动赋值时才会出现(如obj.constructor = ...) -
__proto__同样属于自有属性,仅当被显式设置为实例属性时才被列出(现代代码中极少这么干)
所以真正要做的不是“配合原型链”,而是:
- 明确区分“自有”和“继承”
- 若需检查某个 key 是否来自原型,应单独用
Object.prototype.hasOwnProperty.call(obj, key)或key in obj && !obj.hasOwnProperty(key)
如何判断一个键到底是自有还是继承来的
如果你拿到一个 key(比如 'toString'),想知道它是不是实例自己的:
-
obj.hasOwnProperty('toString')→false(通常是继承的) -
Object.getOwnPropertyNames(obj).includes('toString')→false(证实不在自有属性中) -
typeof obj.toString === 'function'且obj.toString !== Object.prototype.toString→ 可能被重写过,但仍属继承链
想获取“完整结构”时才需考虑原型链延伸
getOwnPropertyNames 只负责当前对象一层。如果真要遍历整个原型链上的自有键(极少见需求),得手动递归:
function getAllOwnKeys(obj) {
const keys = Object.getOwnPropertyNames(obj);
const proto = Object.getPrototypeOf(obj);
return proto ? [...keys, ...getAllOwnKeys(proto)] : keys;
}
⚠️ 注意:这通常没必要,且容易引发无限循环(比如 Object.prototype 的原型是 null,但自定义对象若原型链异常可能出问题)。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











