Object.keys, for in, Object.getOwnPropertyNames, Reflect.ownKeys等方法的区别

165 阅读1分钟

记录一下几种遍历对象方法的区别

定义测试类

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))

4b40def43c724ade8f0383a083dcc364.png

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