js中for...in和object.keys()默认只遍历对象自身可枚举属性,无法直接获取原型链上所有属性名;需手动沿原型链遍历或使用object.getprototypeof()配合object.getownpropertynames()等方法。

JS 原型对象本身不能直接用 for...in 或 Object.keys() 遍历出所有“原型链上的属性名”,因为这些方法默认只操作**当前对象自身可枚举属性**。要获取包括原型链上所有可枚举属性的名称,需手动沿原型链向上遍历。
只获取当前对象自身的可枚举属性名
这是最常用、最安全的方式:
-
Object.keys(obj):返回自身所有可枚举且自有(own)属性名数组(不包含原型链上的) -
Object.getOwnPropertyNames(obj):返回自身所有自有属性名(含不可枚举的,如constructor) -
Object.getOwnPropertySymbols(obj):获取自身自有 Symbol 属性
遍历整个原型链上的可枚举属性名(含继承的)
需手动向上追溯 __proto__ 或用 Object.getPrototypeOf(),并用 for...in(它天然会遍历整个原型链的可枚举属性):
function getAllEnumerableKeys(obj) {
const keys = [];
for (let key in obj) {
keys.push(key);
}
return keys;
}
⚠️ 注意:for...in 会跳过不可枚举属性(如 Array.prototype.map 是不可枚举的),且会包含从 Object.prototype 继承的属性(如 toString)。若想排除 Object.prototype 上的属性,可加过滤:
function getInheritedEnumerableKeys(obj) {
const keys = [];
for (let key in obj) {
if (obj.hasOwnProperty(key)) continue; // 跳过自身的
if (Object.prototype.hasOwnProperty.call(Object.prototype, key)) continue; // 可选:跳过 Object.prototype 上的
keys.push(key);
}
return keys;
}
获取原型链上所有自有属性名(含不可枚举)
如果需要完整“原型链快照”,包括不可枚举属性,得逐级调用 Object.getOwnPropertyNames():
function getAllOwnKeys(obj) {
const keys = new Set();
let current = obj;
while (current !== null && current !== undefined) {
Object.getOwnPropertyNames(current).forEach(k => keys.add(k));
current = Object.getPrototypeOf(current);
}
return Array.from(keys);
}
✅ 这个函数返回原型链上所有对象的自有属性名(去重),包含 constructor、length 等不可枚举属性。
实用建议与注意事项
- 大多数场景只需
Object.keys()或for...in,明确区分“自身”和“继承”是关键 - 避免直接访问
__proto__(已不推荐),统一用Object.getPrototypeOf() - ES6+ 中可结合
Reflect.ownKeys()获取包括 Symbol 的所有自有属性名 - 类实例的原型链通常为:
instance → Class.prototype → Object.prototype → null,可据此预判结果范围











