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

相關文章
相關標籤/搜索