導言 - Lead paragraph
在 JavaScript 開發中,經常需要判斷一個物件是否包含特定屬性。
下面將介紹幾種常用且效能良好的方法,幫助開發者更好地處理這類需求。
在 ECMAScript 2022 (ES13) 以前,有兩種較多人使用的傳統方法可以檢查 JS 對象是否具有任何自定義屬性:
in
operator
hasOwnProperty()
function
而在 ES13 的 “hasOwn()
” 出現以後,正式自 ECMAScript 2022(ES13) 起,就不再需要使用 hasOwnProperty()
了,因為我們可以使用新的內置 Object.hasOwn()
方法。
in 運算符 - in Operator
這是 JavaScript 中內建的運算子,可以檢查物件是否包含指定的屬性,包括直接擁有的和透過原型鏈繼承的屬性。
const obj = { name: 'John', age: 30 };
console.log('name' in obj);
console.log('gender' in obj);
Object.hasOwn()
⚠️ Object.hasOwn()
旨在取代 Object.prototype.hasOwnProperty()
。
如果指定的對象自身有指定的屬性,則返回 true。如果屬性是繼承的或者不存在,該方法返回 false。
它與 in 運算符不同,因為它不檢查繼承的屬性。
const obj = { name: 'John', age: 30 };
console.log(Object.hasOwn(obj, 'name'));
console.log(Object.hasOwn(obj, 'gender'));
官方文檔:Object.hasOwn() - JavaScript | MDN
Object.prototype.hasOwnProperty()
已過時,但還可使用
這是 JavaScript 中內建的方法,可用於檢查物件自身是否包含指定的屬性,而不是透過原型鏈繼承而來的屬性。
const obj = { name: 'John', age: 30 };
console.log(obj.hasOwnProperty('name'));
console.log(obj.hasOwnProperty('gender'));
Object.keys()
使用 Object.keys()
將物件的屬性名稱轉換為一個陣列,然後可以透過陣列的方法來判斷是否包含指定的屬性。
const obj = { name: 'John', age: 30 };
console.log(Object.keys(obj).includes('name'));
console.log(Object.keys(obj).includes('gender'));
Object.prototype.hasOwnProperty.call()
這是 hasOwnProperty()
的一個變種,可以解決某些特殊情況下的問題,特別是當物件的 hasOwnProperty()
被覆寫時。
const obj = { name: 'John', age: 30 };
console.log(Object.prototype.hasOwnProperty.call(obj, 'name'));
console.log(Object.prototype.hasOwnProperty.call(obj, 'gender'));
Object.getOwnPropertyNames()
Object.getOwnPropertyNames()
會返回物件本身所有屬性(不包括繼承的屬性)的名稱,可以用來檢查是否存在指定屬性。
const obj = { name: 'John', age: 30 };
console.log(Object.getOwnPropertyNames(obj).includes('name'));
console.log(Object.getOwnPropertyNames(obj).includes('gender'));
undefined OR !==
這是一種比較老式的方法,在現代 JavaScript 中不太常見,但仍然有效。
通過檢查屬性是否等於 undefined
,來判斷物件是否包含指定的屬性。
const obj = { name: 'John', age: 30 };
console.log(obj.name !== undefined);
console.log(obj.gender !== undefined);
方法與使用情境對比
方法 | 使用情境 |
---|
in 運算符 | 檢查物件是否包含指定屬性,包括原型鏈中的屬性。 需要考慮物件及其原型鏈中是否有指定屬性時使用。 |
Object.prototype.hasOwn() | 指定對象具有指定屬性作為其自己的屬性。 只需要判斷物件自身是否擁有指定屬性時使用。 |
Object.prototype.hasOwnProperty() | 檢查物件是否包含指定屬性,且不考慮原型鏈繼承。 只需要判斷物件自身是否擁有指定屬性時使用。 |
Object.keys() | 將物件的屬性名稱轉換為陣列,方便進行遍歷或其他陣列方法。 不需關心屬性的值,只需判斷是否存在時使用。 |
Object.getOwnPropertyNames() | 獲得物件本身所有屬性(不包括繼承的屬性)的名稱。 只需檢查物件本身的屬性時使用。 |
Object.prototype.hasOwnProperty.call() | hasOwnProperty 的變種,解決某些特殊情況下的問題。 可以用在 hasOwnProperty 方法被覆寫時。 |
這些方法在不同的使用情境中有不同的優勢。
選擇適合的方法取決於需求以及是否需要考慮物件的原型鏈。
看到很多文章都使用 hasOwnProperty()
或 in
運算符,ChatGPT 也推薦使用兩者擇一,原因是因為它們的效能相對較好且用法直觀。
但是 ChatGPT GPT-3.5 架構,其訓練數據截止日期為 2021 年 9 月。
並沒有涵蓋到 ECMAScript 2022(ES13)的 hasOwn()
問世資訊,經過查閱大量文章、教學與實測後,使用 hasOwn()
會比 hasOwnProperty()
好。
若只需判斷物件自身是否擁有指定屬性,較簡單的情況下可以選擇 hasOwn()
;若需考慮原型鏈中的屬性,則選擇 in
運算符。
Object.keys()
和 Object.getOwnPropertyNames()
通常用於需要操作物件所有屬性名稱的場景,但不需關心屬性值本身。
Object.prototype.hasOwnProperty.call()
主要用於解決特殊情況下的問題,不常使用,但了解它可以解決覆寫 hasOwnProperty()
的問題,但 Object.hasOwn()
直接克服了這些問題,因此是首選。。
結論 - Concluding
開發者可以根據需求選擇適合的方法,提高程式效率。
參考資料 - Reference
[1] ChatGPT
https://chat.openai.com/
[2] The Difference Between in and hasOwnProperty in JavaScript - Mastering JS
https://masteringjs.io/tutorials/fundamentals/hasownproperty
[3] JavaScript: hasOwn() — new way to check if Object has property | by Igor Gonchar | Medium
https://igorgonchar.medium.com/javascript-hasown-new-way-to-check-if-object-has-property-b93810e47070
[4] 檢驗物件是否包含屬性 - Google Search
https://www.google.com/search?q=%E6%AA%A2%E9%A9%97%E7%89%A9%E4%BB%B6%E6%98%AF%E5%90%A6%E5%8C%85%E5%90%AB%E5%B1%AC%E6%80%A7