JS:获取对象属性有哪些方法?

8,361 阅读3分钟

对象的两类属性

对象的属性有两种类型:字符串和 Symbol。

var sybProp = Symbol()
var strProp = 'str'
var objProp = {}

var obj = {
  [sybProp]: 'This is a String property',
  [strProp]: 'This is a Symbol property',
  [objProp]: 'This is also a String property'
}

obj
// {
//   str: "This is a String property",
//   [object Object]: "This is also a String property",
//   Symbol(): "This is a Symbol property"
// }

因为对象只支持字符串和 Symbol 两种类型的属性,如果我们使用的是任何其他类型值作为属性名,最后都会被转为字符串。比如这里的 [objProp]objProp 是个对象,用它创建完 obj 后,再看看,就变成字符串 "[object Object]" 了。

获取属性的方法

为了更好的演示,我们先来定义一个操作对象。

var obj = {
  str: 'This is a String property',
  [Symbol()]: 'This is a Symbol property'
}
// 再定义一个不可枚举属性
Object.defineProperty(obj, 'unenum', {
  value: 'This is a non-enumerable property',
  writeable: true,
  enumerable: false,
  configurable: true
})
Object.defineProperty(obj, Symbol('unenum'), {
    value: 'This is a non-enumerable Symbol property',
    writeable: true,
    enumerable: false,
    configurable: true
})
// 
Object.setPrototypeOf(obj, { foo: 'bar', [Symbol('foo')]: 'bar' })

这个对象覆盖了下面要说的不同方法之间的区别。包括一个字符串属性和 Symbol 属性,同时还具有一个不可枚举字符串属性和 Symbol 属性。另外,还重置了原型对象,原型对象里包含了一个字符串属性和 Symbol 属性(都是可枚举的)。

下面展示了 obj 的数据结构。

image.png

Object.keys/values/entries

这三个方法都是用来获取对象上的属性集合的。只不过,Object.keys 是用来获取属性名集合,Object.values 是用来获取属性值集合,Object.entries 则是用来获取属性键-值对集合的。

Object.keys(obj) // ["str"]
Object.values(obj) // ["This is a String property"]
Object.entries(obj) // [ ["str", "This is a String property"] ]

通过结果可以发现,除了返回结果的不同之外,这三个属性有一个共同点:只处理 obj 自身的可枚举字符串属性

Object.getOwnPropertyNames(obj)

顾名思义,Object.getOwnPropertyNames(obj) 获取的是对象自身的属性集合。但具体是哪些属性呢?我们看下:

Object.getOwnPropertyNames(obj) // ["str", "unenum"]

由结果可知,返回了 obj 自身的所有字符串属性(包括不可枚举的),但不包括 Symbol 属性。

Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols(obj) 是跟 Object.getOwnPropertyNames(obj) 相对应的,返回 obj 自身的所有 Symbol 属性(包括不可枚举的)

Object.getOwnPropertySymbols(obj) // [Symbol(), Symbol(unenum)]

由结果可知,返回了 obj 自身的所有 Symbol 属性(包括不可枚举的),但不包括字符串属性。

Reflect.ownKeys(obj)

Reflect.ownKeys(obj) 可以看做是 Object.getOwnPropertyNames(obj) + Object.getOwnPropertySymbols(obj),即获得 obj 自身的所有属性集合

Reflect.ownKeys(obj) // ["str", "unenum", Symbol(), Symbol(unenum)]

for-in

再来看看 for-in 语句遍历对象的结果为何。

for (let prop in obj) {
    console.log(prop) // "str" -> "foo"
}

由此可见:for-in 返回的是对象自身及所在原型链上的所有可枚举字符串属性

将 for-in 语句配合 obj.hasOwnProperty(prop) 方法一起使用,就能得到跟 Object.keys/values/entries 方法一样的效果——即返回对象自身的可枚举字符串属性。

for (let prop in obj) {
  if (obj.hasOwnProperty(prop)) {
    console.log({ key: prop, value: obj[prop], pair: [prop, obj[prop]] })
  }
}
// {key: "str", value: "This is a String property", pair: ["str", "This is a String property"] }

总结

方法 返回值 备注
Object.keys/values/entries 对象自身的可枚举字符串属性
Object.getOwnPropertyNames(obj) 对象自身的所有可枚举、不可枚举的字符串属性
Object.getOwnPropertySymbols(obj) 对象自身的所有可枚举、不可枚举的 Symbol 属性
Reflect.ownKeys(obj) 对象自身的所有可枚举、不可枚举的字符串属性、Symbol 属性。 等同于 Object.getOwnPropertyNames(obj) +  Object.getOwnPropertySymbols(obj)  的效果。
for (let prop in obj) {} 对象自身及所在原型链上的所有可枚举字符串属性

(正文完)


广告时间(长期有效)

我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。

(完)