JavaScript 判断属性或者遍历属性: in, for in, Object.keys, Reflect.ownKeys etc.

判断属性存在或者遍历属性是平常开发中常常会用到。只是针对这些操做符、语句、方法,有些混淆。因此总结一下。javascript

对象属性

对象属性目前只能是字符串值或者 symbol 值html

A property key value is either an ECMAScript String value or a Symbol valuejava

ECMAScript® 2020 Language Specificationes6

明确了这个规则后,开始下面的说明。web

Property Attributes

翻译为属性的属性?这个概念我也有点说不清,看看下面的参考数组

attribute和property在英语里有什么区别? - 知乎markdown

Property Attributes 有 Value、Writable、Enumerable、Configurable。这个能够经过 Object.getOwnPropertyDescriptor 获取值。经过 Object.defineProperty 进行定义或者修改。oop

另外还有 Get、Setthis

本文的重点是讨论 Enumerable,这个值设置为 false 后,属性是不可遍历的。spa

可是不可遍历了,我仍是须要获取这个属性该怎么办?

in 操做符

指定的属性在指定的对象或其原型链中,则in 运算符返回true

Reflect.hasin 的效果相同

这里的重点是 in 会检查原型链

console.log(length in []);  // true
// 继承的 Symbol
console.log(Symbol.iterator in []);  // true
// 继承的方法
console.log('toString' in []);  // true
复制代码

for...in 语句

for...in 循环只遍历可枚举属性(包括它的原型链上的可枚举属性)

所以 for...in 的行为受到 Enumerable 的控制

for in 区别 // 遍历除了 symbol 之外的可枚举属性

let obj = {
  [Symbol('my_key')]: 1,
  enum: 2,
  nonEnum: 3
};
Object.defineProperty(obj,
  'nonEnum', { enumerable: false });
console.log(Object.keys(obj))

let obj2 = Object.create(obj)
obj2.myVal = 5
console.log(obj2);  // { myVal: 5 }

for (var prop in obj2) {
  console.log('obj2 prop: ', prop);  // myVal, enum
}

复制代码

Object 对象的一些方法

Object.keys

会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

// 省略上面的代码
Object.keys(obj)  // ['enum']
Object.keys(obj2)  // ['myVal']
复制代码

Object.getOwnPropertyNames

返回一个由指定对象的全部自身属性的属性名(包括不可枚举属性但不包括Symbol值做为名称的属性)组成的数组。

// 省略上面的代码
Object.getOwnPropertyNames(obj)  // ['enum', 'nonEnum']
复制代码

Object.prototype.hasOwnProperty 用来判断对象自身属性。

一个经常使用的判断:遍历一个对象的全部自身属性

var buz = {
  fog: 'stack'
};

for (var name in buz) {
  if (buz.hasOwnProperty(name)) {
    console.log('this is fog (' + 
      name + ') for sure. Value: ' + buz[name]);
  }
  else {
    console.log(name); // toString or something else
  }
}
复制代码

Object.getOwnPropertySymbols

返回一个给定对象自身的全部 Symbol 属性的数组

// 省略上面的代码
Object.getOwnPropertySymbols(obj)  // [ Symbol(my_key) ]
复制代码

Reflect.ownKeys

上面的方法操做符,饶了一圈。和 Enumerable Symbol 的有无打交道。

有没有方法可以拿到全部的属性 (我全都要.webp)

答案就是: Reflect.ownKeys

// 省略上面的代码
Reflect.ownKeys(obj)  // [ Symbol(my_key), 'enum', 'nonEnum' ]
复制代码

总结

对象属性目前只能是字符串值或者 symbol 值。因此下面的状况会出现 toPrimitive 或者 toString 的转换

let obj3 = {
    [obj]: 33
}
// { '[object Object]': 33 }
复制代码

固然须要使用对象做为 key, 须要用到 Map 了,这些是后话。

通常状况下都是用 Object.keys 来遍历自身可枚举属性。Object.keys 是 ES5 的标准。

之前 ES3 的时候是须要 in 操做符 和 hasOwnProperty 配合使用

全都要的状况: Reflect.ownKeys

要考虑 Enumerable 为 false 时, 用 Object.getOwnPropertyNames 要考虑 Symbol 时, 用 Object.getOwnPropertySymbols

参考连接

Symbols in ECMAScript 6

MDN

in - JavaScript | MDN Keys in Javascript objects can only be strings? - Stack Overflow

Object.prototype.hasOwnProperty() - JavaScript | MDN

相关文章
相关标签/搜索