总结写在最前面
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.prototypeOf、Object.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版本
前端萌新,如有错误请指正~