记录一下几种遍历对象方法的区别
定义测试类
class NObject {
constructor () {
this.name = 'yu'
this.age = 12
}
// class内部原型方法
sayName () {
console.log(this.name)
}
}
// class外部定义的原型方法
NObject.prototype.sayAge = function sayAge () {
console.log(this.age)
}
创建测试实例并添加属性
// 创建实例
const obj = new NObject()
// 添加可枚举属性a
obj.a = 'a'
// 添加不可枚举属性b
Object.defineProperty(obj, 'b', {
value: 'b',
enumerate: false,
writable: false,
configuration: false
})
// 添加可枚举Symbol属性
obj[Symbol.for('s1')] = 's1'
// 添加不可枚举Symbol属性
Object.defineProperty(obj, Symbol.for('s2'), {
value: 's2',
enumerate: false,
writable: false,
configuration: false
})
// 打印NObject的原型,查看原型中属性的可枚举值,如下图,可以看到sayAge是可枚举的,sayName是不可枚举的
console.log(Object.getOwnPropertyDescriptors(NObject.prototype))
chrome浏览器方法测试
console.log(Object.keys(obj)) // ['name', 'age', 'a']
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(s1), Symbol(s2)]
console.log(Object.getOwnPropertyNames(obj)) // ['name', 'age', 'a', 'b']
console.log(Reflect.ownKeys(obj)) // ['name', 'age', 'a', 'b', Symbol(s1), Symbol(s2)]
const forInArr = []
for (const k in obj) {
forInArr.push(k)
}
console.log(forInArr) // ['name', 'age', 'a', 'sayAge']
测试结果
| 方法/属性 | 可枚举 | 不可枚举 | Symbol | 原型 |
|---|---|---|---|---|
| Object.keys | 是 | 否 | 否 | 否 |
| Object.getOwnPropertySymbols | 否 | 否 | 是 | 否 |
| Object.getOwnPropertyNames | 是 | 是 | 否 | 否 |
| Reflect.ownKeys | 是 | 是 | 是 | 否 |
| for in | 是 | 否 | 否 | 是 |
- Object.keys,获取自身可枚举属性。不包括不可枚举属性,原型属性,Symbol
- Object.getOwnPropertySymbols,只可获取对象的Symbol属性(包含可枚举和不可枚举)
- Object.getOwnPropertyNames,获取自身所有属性名称,包括不可枚举属性。不包括Symbol,不包括原型
- Reflect.ownKeys,获取自身所有属性名称,包括不可枚举属性,Symbol。不包括原型(其实就是Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和)
- for in,遍历所有可枚举属性,原型属性。不包括不可枚举属性,Symbol