【JS學習筆記】如何檢查物件的屬性?


Posted by Annie-Chien on 2022-12-15

這篇文章要介紹檢查物件裡是否存在某個屬性的三種方式。

1. 直接試著存取該屬性

第一方法非常簡單,那就是直接試著存取該屬性看看!若該屬性不存在於物件中,則會回傳 undefined。因此可以根據此特性來判斷某個屬性是否存在於物件當中。

const obj={
  name: 'Justin',
  age: 28,
  birthday: '1994/03/01'
}
console.log(obj.name); // 'Justin'
console.log(obj.gender); // undefined
console.log(obj['age']); // 28

不過這個方法有個致命的缺點:當今天屬性的值原本就是 undefined 時,就會造成判斷錯誤。

2. 運算子 in

或者,也可以使用 JS 內建的運算子 in 來判斷屬性是否存在於物件當中。'propertyName' in obj 用來判斷屬性'propertyName'是否存在於物件 obj 中,回傳 true 代表存在,false 則為不存在。
我們繼續沿用上個例子:

console.log('name' in obj); // true
console.log('gender' in obj); // false

3. Object.prototype.hasOwnProperty()

使用方法為 object.hasOwnProperty('propertyName'),其效果與關鍵字 in 類似(為什麼說「類似」呢先賣個關子)。

console.log(Object.hasOwnProperty('name')); // true
console.log(Object.hasOwnProperty('gender')); // false

in 與 hasOwnProperty()

從上面的例子來看,這兩個的的功能一模一樣。但其實它們有個很大的不同點,而這是從上面的例子看不出來的。

in 會沿著原型鏈往上爬,沿路檢查是否有該屬性。而 hasOwnProperty() 則只會檢查物件「本身」是否含有該屬性。

舉一個全新的例子 🌰

const animal = {
  sleep() {
    console.log('Zzzz...');
  },
};

const pet = {
  name: 'Judy',
  age: 2,
  type: 'dog',
  greet() {
    console.log('WOOF!WOOF!');
  },
};

// 透過 setPrototypeOf()來指定物件與物件之間的原型關係。

Object.setPrototypeOf(pet, animal);

// Object.setPrototypeOf(pet, animal) 將會把物件 animal 指定作為物件 pet 的原型。

先把 pet 印出來看看!
console.log(pet);

這張圖片的重點在物件 pet 內有個叫做 [[prototype]] 的屬性!
然後這個 [[prototype]] 屬性是用來指向 pet 物件的原型(也就是我們剛剛手動設定的物件 animal),所以你可以看到 sleep method 就在裡面。
因此,如果你透過物件 pet 來呼叫 sleep 是沒問題的喔~請看

pet.sleep(); // Zzzz...

💌 溫馨小叮嚀:我們是無法直接存取這個 [[prototype]] 屬性的,因為它屬於內部屬性。

好了,一切我們必要的東西都已經設定完畢!現在就可來測試看看 in 和 hasOwnProperty() 的不同之處。

console.log(pet.hasOwnProperty('sleep')); // false
console.log('sleep' in pet); // true

太好了!
結果跟與我們的期待相符 ☺️
因為 sleep method 並不直接存在於物件 pet 裡,因此 hasOwnProperty 會回傳 false。而 in 則會幫我們沿著原型鏈一路網上尋找,如果成功找到就會回傳 true,而在這個例子當中,in 的確找到了 sleep method!

同場加應:Object.hasOwn()

寫到一個段落的時候,看到 PJCHEN der 的這部 YouTube 影片,才知道原來還有一個酷東西叫做 Object.hasOwn()

hasOwn() 的功用和 hasOwnProperty 基本上是一樣的,都是用來檢查特定屬性是否直接存在於物件當中,使用方式稍稍不同: Object.hasOwn(obj, 'propertyName')
最最最重要的是,MDN 推薦大家用 hasOwn() 取代 hasOwnProperty()。原因有幾個:
1. hasOwnProperty() 會被覆寫
當今天你要檢查的物件內剛好有一個屬性叫做 hasOwnProperty(),那麼當你試著呼叫 hasOwnProperty() 時,會直接執行你在物件內自己定義的內容,而不會執行判斷屬性是否存在的內建功能。

const foo = {
  hasOwnProperty() {
    return false;
  },
  bar: 'The dragons be out of office',
};

foo.hasOwnProperty('bar'); //false,因為已經被 foo 裡面的 hasOwnProperty 覆蓋
Object.hasOwn(foo, 'bar'); //true,正常發揮!

MDN 還舉了一個例子,那就是當我們使用 Object.create(null) 來創造一個乾淨的空物件時(乾淨指的是它並沒有繼承 Object.prototype 裡面的屬性和方法),無法使用 hasOwnProperty!

const foo = Object.create(null);
foo.hasOwnProperty('foo');
//Uncaught TypeError: foo.hasOwnProperty is not a function
Object.hasOwn(foo, 'prop'); // true,正常發揮!

之所以 hasOwn 都能正常運作是因為 hasOwn 這個方法就直接存在於 Object 內,但是 hasOwnProperty 則是被定義在 Object.prototype 裡。

參考資料

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn


#javascript







Related Posts

資結、Data structure 1-- linked list

資結、Data structure 1-- linked list

 JQ總務處|處理JSON資料|深入淺出jQuery

JQ總務處|處理JSON資料|深入淺出jQuery

JavaScript 變數生存範圍:var, let, const and scope

JavaScript 變數生存範圍:var, let, const and scope


Comments