精准遍历对象属性需先明确目标属性类型:object.keys()仅返回可枚举字符串键;object.getownpropertynames()返回所有字符串键(含不可枚举);reflect.ownkeys()返回全部自有键(字符串+symbol)。

要精准遍历对象的属性,关键不是“用哪个方法更快”,而是**明确你想遍历哪类属性**:可枚举的?不可枚举的?Symbol 类型的?继承来的?三个方法覆盖范围不同,选错就漏数据或混入无关项。
Object.keys():只拿「可枚举 + 字符串键」
它返回一个数组,包含对象自身所有可枚举(enumerable: true)且键为字符串的属性名。不包括 Symbol 属性,也不包括不可枚举属性(如 Object.prototype.toString 的属性),更不会访问原型链。
- 适合日常遍历——比如把对象转成 JSON、批量处理表单字段、生成 HTML 属性列表
- 注意:
Object.keys({a:1, [Symbol('b')]:2, get c(){}})只返回['a'];c是 getter,但若没设 enumerable(默认 false),也不会出现
Object.getOwnPropertyNames():拿全「字符串键」,不管是否可枚举
它返回对象自身所有字符串类型键名,无论 enumerable 是 true 还是 false。依然忽略 Symbol 键。
- 适合需要访问内部属性的场景——比如检查对象是否有
length、name等不可枚举自有属性,或做属性白名单校验 - 例子:
Object.getOwnPropertyNames(Object.prototype)会返回['constructor', '__defineGetter__', '__defineSetter__', 'hasOwnProperty', ...'](这些大多不可枚举)
Reflect.ownKeys():真正「全量自有键」——字符串 + Symbol
它返回对象自身所有键名,包括可枚举/不可枚举的字符串键,以及所有 Symbol 键,严格等价于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。
- 适合元编程、深克隆、序列化工具、调试器等需要完整还原对象结构的场景
- 例如:
const obj = {a:1}; obj[Symbol('s')] = 'sym'; Object.defineProperty(obj, 'b', {value:2, enumerable:false}); Reflect.ownKeys(obj)返回['a', 'b', Symbol(s)]
如何组合使用,实现「按需精准遍历」
没有万能方法,但可以按目标组合判断逻辑:
- 只遍历可枚举字符串属性 → 直接用
Object.keys() - 要包含不可枚举字符串属性(如某些库内部标记)→ 用
Object.getOwnPropertyNames() - 必须兼容 Symbol 键(如 React element 的
$$typeof)→ 必须用Reflect.ownKeys() - 想排除继承属性又保留 Symbol + 不可枚举字符串 →
Reflect.ownKeys()是唯一选择
不复杂但容易忽略:遍历前先确认属性是否在当前对象上(hasOwnProperty 或 Object.prototype.hasOwnProperty.call(obj, key)),避免误操作原型链上的同名属性。











