Object.keys()和Object.values()最常用但只返回自有可枚举属性;for...in需hasOwnProperty过滤原型链;Object.entries()适合键值同处理;Reflect.ownKeys()唯一获取所有自有键(含Symbol和不可枚举)。
这两个方法是日常开发中最直接的取键/取值方式,但要注意它们**不会遍历原型链上的属性**,也**跳过不可枚举属性(如 Object.defineProperty 设置的 enumerable: false 的属性)**。
Object.keys(obj) 返回字符串数组,比如 ['a', 'b']
Object.values(obj) 返回值数组,顺序与 keys() 一致for...in 会遍历对象自身及原型链上所有**可枚举属性**,这是它和 Object.keys() 的关键区别。不加防护直接用,很容易误读到 toString、hasOwnProperty 等继承方法。
obj.hasOwnPropert
y(key) 判断是否为自有属性Map、Set 等内置集合类型(它们没有可枚举属性)Object.freeze())或属性设为不可枚举,for...in 仍会跳过Object.entries(obj) 返回二维数组,如 [ ['a', 1], ['b', 2] ],天然适配 for...of 或 Array.prototype.map() 等数组方法。
keys() 和 values() 更高效(底层只遍历一次)for (const [key, value] of Object.entries(obj)) { ... }
Symbol('a') 类型的键)当你需要完整“镜像”一个对象结构(比如做深拷贝、序列化、代理拦截),Reflect.ownKeys() 是最全的选择。它等价于 Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))。
立即学习“Java免费学习笔记(深入)”;
Object.getOwnPropertyDescriptor() 或 Object.getPrototypeOf() 判断constructor 或 __proto__ 这类内部属性const obj = { a: 1 };
Object.defineProperty(obj, 'b', { value: 2, enumerable: false });
const sym = Symbol('c');
obj[sym] = 3;
console.log(Reflect.ownKeys(obj)); // ['a', 'b', Symbol(c)]
遍历对象看似简单,真正容易出问题的是对“哪些键该出现”的预期不一致:有人以为 for...in 就是“所有键”,有人以为 Object.keys() 会包含 Symbol。实际选择哪个方法,取决于你是否关心原型、是否需要不可枚举属性、是否要处理 Symbol——这些细节在调试时往往卡很久。