在 JavaScript 中,for…in、Object.keys() 和 Reflect.ownKeys() 是三种常用来遍历对象属性的方法,但它们的行为和适用场景各不相同。下面简述下它们的工作原理、适用场景以及各自的区别。
for…in
概念:for…in用于遍历对象的可枚举属性,不仅遍历对象自身的属性,也会遍历其原型链上的可枚举属性。
特点:
- 遍历对象自身和继承的可枚举属性。
- 只会遍历可枚举的属性(
enumerable: true)。
缺点:
- 如果对象继承了原型链上的属性,且这些属性是可枚举的,for…in 也会遍历这些属性,可能导致意外行为。若只想遍历对象自身的属性,需要配合
hasOwnProperty()来过滤掉继承的属性
const obj = { a: 1, b: 2 }
Object.getPrototypeOf(obj).c = 3
for (let key in obj) {
console.log(key) // 输出: "a", "b", "c"(包括继承的 c)
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(key) // 仅输出 "a", "b"
}
}
Object.keys()
概念:Object.keys() 返回对象自身的可枚举属性组成的数组,不包括原型链上的属性。
特点:
- 仅返回对象自身的可枚举属性(不会遍历原型链上的属性)。
- 返回结果是一个数组,数组中的每一项是对象的属性名称。
Reflect.ownKeys()
概念:Reflect.ownKeys() 返回对象的所有自身属性,包括可枚举和不可枚举的属性,且会返回符号(Symbol)属性。
特点:
- 返回对象自身的所有属性,无论它们是否可枚举。
- 能够遍历符号属性(Symbol)。
优点:
- 完整遍历对象自身的属性,包含不可枚举和 Symbol 属性,适用于高级场景。
缺点:
- 由于它返回所有属性,包括不可枚举的属性,可能会产生不必要的结果,需要仔细处理。
总结
选择建议:
for…in:适合需要遍历所有可枚举属性(包括继承的属性)的场景。Object.keys():适合只需要遍历对象自身可枚举属性的场景,使用频率较高。Reflect.ownKeys():适合需要完整获取对象自身属性(包括不可枚举和符号属性)的高级用法。