Object.keys(obj)可获取实例自身可枚举属性;遍历整个原型链需用Object.getPrototypeOf逐级向上并收集Object.keys结果;不可枚举属性和私有字段需特殊处理。

要手动遍历一个实例对象的所有自身属性(不包括原型链上的),直接用 Object.keys(obj) 或 for...in 配合 hasOwnProperty 即可;但若目标是“遍历所有实例属性 + 原型链上可枚举的属性”,就得顺着 __proto__ 一层层往上走。
只遍历实例自身的可枚举属性
这是最常见需求:排除继承来的属性,只看对象自己拥有的。
-
Object.keys(obj)—— 返回自身所有可枚举、自有属性的字符串数组(不含 Symbol) -
Object.getOwnPropertyNames(obj)—— 包含不可枚举的自有属性(如constructor) -
Object.getOwnPropertySymbols(obj)—— 获取自身 Symbol 类型的自有属性
手动遍历整个原型链上的可枚举属性
需要从实例开始,逐级访问 obj.__proto__,直到到达 null。注意:只收集 for...in 能访问到的(即可枚举)属性,且避免重复(同名属性在上层会被遮蔽,实际访问时已不可见,但遍历时仍可能遇到)。
简单实现:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
function getAllEnumerableKeys(obj) {
const keys = new Set();
let current = obj;
while (current !== null) {
Object.keys(current).forEach(key => keys.add(key));
current = Object.getPrototypeOf(current);
}
return Array.from(keys);
}
说明:
– 用 Set 自动去重,因为不同层级可能有同名属性(但实际只有最靠近实例的那个生效)
– 使用 Object.getPrototypeOf(current) 比直接读 __proto__ 更规范、更安全
区分属性来源:哪些是实例的?哪些来自原型?
如果想明确知道每个属性定义在哪一层,可以边遍历边记录:
function getKeysByLevel(obj) {
const result = [];
let current = obj;
let level = 0;
while (current !== null) {
const ownKeys = Object.keys(current);
if (ownKeys.length > 0) {
result.push({ level, from: level === 0 ? 'instance' : `prototype #${level}`, keys: ownKeys });
}
current = Object.getPrototypeOf(current);
level++;
}
return result;
}
调用后会返回类似:
[{ level: 0, from: 'instance', keys: ['name'] },
{ level: 1, from: 'prototype #1', keys: ['sayHi'] },
{ level: 2, from: 'prototype #2', keys: ['toString'] }]
注意不可枚举属性和私有字段
Object.keys / for...in 都跳过不可枚举属性(如 Object.defineProperty(obj, 'hidden', { enumerable: false }) 定义的)。若需包含它们,必须用 Object.getOwnPropertyNames 或 getOwnPropertyDescriptors,但这些只作用于当前对象,不自动跨原型链——你要手动对每一层都调用一次。
另外:
– #privateField 是语法级私有,无法通过任何反射 API 访问
– Symbol 属性默认不可枚举,需显式用 Object.getOwnPropertySymbols 提取
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










