JavaScript中获取对象属性的方法汇总

2,943 阅读3分钟

总结写在最前面

for...in 获取当前对象及其原型链上的所有可枚举属性
Object.keys 获取当前对象上的所有可枚举属性
Object.getOwnPropertyNames 获取当前对象上的所有可枚举和不可枚举属性
Object.getOwnPropertySymbols 获取当前对象上所有Symbol属性
Reflect.ownKeys 获取当前对象上所有可枚举、不可枚举属性以及Symbol属性
Object.prototypeOf 获取对象原型链上一级的对象
Reflect.prototypeOf 获取对象原型链上一级的对象

所有通过Object和Reflect方法获取对象的属性,都无法访问到对象原型链上的属性。

Object.keys 是获取到对象属性的所有方法中范围最小的一种方法

Reflect.ownKeys 是获取到对象属性的所有方法中范围最大的一种方法

此外 Reflect.ownKeys = Object.getOwnPropertyNames + Object.getOwnPropertySymbols

一般我们日常使用,如果只是想访问当前对象上的属性使用Object.keys(),如果想访问当前对象以及其原型链上的属性最好使用for...in。因为如果对象的创建者创建的时候故意将某个属性设置为enumerable: false或者用symbol来设置属性,那么他的本意就是这些属性应该是对象内部属性,不应该暴露给外部用户。

以下是测试样例:

测试对象

function Son () {
  let sonSymbol = Symbol('son`s symbol')
  this.sonEnumProp = 'son`s enumerable prop'
  this[sonSymbol] = 'son`s symbol prop'
  Object.defineProperty(this, 'sonNotEnumProp', {
    value: 'son`s unenumerable prop',
    enumerable: false
  })
  if (typeof this.fatherEnumProp !== 'string') {
    let fatherSymbol = Symbol('father`s symbol')
    Son.prototype.fatherEnumProp = 'fathers enumerable prop'
    Son.prototype[fatherSymbol] = 'father`s symbol prop'
    Object.defineProperty(Son.prototype, 'fatherNotEnumProp', {
      value: 'father`s unenumerable prop',
      enumerable: false
    })
  }
}

这里定义了一个构造函数 Son ,这个构造函数为他的实例添加了三个属性:

  • 可枚举属性 sonEnumProp
  • 不可枚举属性 sonNotEnumProp
  • Symbol属性 sonSymbol

并且在第一次实例化的时候为Son的原型对象添加三个属性:

  • 可枚举属性 fatherEnumProp
  • 不可枚举属性 fatherNotEnumProp
  • Symbol属性 fatherSymbol

这样用于测试的构造函数就完成了,我们实例化一个对象obj,然后再这个对象的基础上开始测试

var obj = new Son() 

for...in

for...in会遍历当前对象以及其原型链上对象的所有可枚举属性

// FOR IN 获取对象实例及其原型链上的所有可枚举属性
var res = []
for (var prop in obj) {
  res.push(prop)
}
console.log('for...in: ', res)

输出: for...in: [ 'sonEnumProp', 'fatherEnumProp' ]

Object.keys

Object.keys 获取当前对象上的所有可枚举属性

// Object.keys 获取当前对象上的所有可枚举属性
console.log('Object.keys: ', Object.keys(obj))

输出: Object.keys: [ 'sonEnumProp' ]

Object.getOwnPropertyNames

Object.getOwnPropertyNames 获取当前对象上的所有可枚举和不可枚举属性

// Object.getOwnPropertyNames 获取当前对象上的所有可枚举和不可枚举属性
console.log('Object.getOwnPropertyNames: ', Object.getOwnPropertyNames(obj))

输出: Object.getOwnPropertyNames [ 'sonEnumProp', 'sonNotEnumProp' ]

Object.getOwnPropertySymbols

Object.getOwnPropertySymbols 获取当前对象上所有Symbol属性

// Object.getOwnPropertySymbols 获取当前对象上所有Symbol属性
console.log('Object.getOwnPropertySymbols: ', Object.getOwnPropertySymbols(obj))

输出: Object.getOwnPropertySymbols [ Symbol(son`s symbol) ]

Reflect.ownKeys

Reflect.ownKeys 获取当前对象上所有可枚举、不可枚举属性以及Symbol属性

// Reflect.ownKeys 获取当前对象上所有可枚举、不可枚举属性以及Symbol属性
console.log('Reflect.ownKeys: ', Reflect.ownKeys(obj))

输出: Reflect.ownKeys [ 'sonEnumProp', 'sonNotEnumProp', Symbol(son`s symbol) ]

Object.prototypeOf、Reflect.prototypeOf

Reflect.prototypeOfObject.prototypeOf 获取当前对象上所有可枚举、不可枚举属性以及Symbol属性

// Object.prototypeOf 获取对象原型链上一级的对象
console.log('Object.getPrototypeOf: ', Object.getPrototypeOf(obj))

// Reflect.prototypeOf 获取对象原型链上一级的对象
console.log('Reflect.getPrototypeOf: ', Reflect.getPrototypeOf(obj))

输出:

Object.getPrototypeOf Son {
  fatherEnumProp: 'fathers enumerable prop',
  [Symbol(father`s symbol)]: 'father`s symbol prop' }
Reflect.getPrototypeOf Son {
  fatherEnumProp: 'fathers enumerable prop',
  [Symbol(father`s symbol)]: 'father`s symbol prop' }

写在最后

作者:HAHAHA同学

测试环境为Node 10.15.3版本

前端萌新,如有错误请指正~