前言
在 JavaScript 開發中,我們經常需要檢查一個物件是否擁有某個特定的屬性。最近,我在一個處理表格欄位排序的專案中嘗試使用 Object.hasOwn()
方法,但很快發現這個方法與我的開發環境不相容。這篇文章將分享我的經歷,以及我是如何找到並實施一個既安全又相容的解決方案的。
初次嘗試:Object.hasOwn()
起初,我的程式碼是這樣的:
1 | var sortDataByOrder = function (dataMap, displayOrder) { |
我選擇使用 Object.hasOwn()
,因為它是檢查物件是否擁有自有屬性的現代方法,並且經常被推薦作為替代傳統 hasOwnProperty
的選項。
Object.hasOwn()
是 ECMAScript 2022 中引入的新方法,其設計目的是提供一種更簡潔且不易出錯的語法。與傳統的 hasOwnProperty
相比,它具有以下優點:
- 簡潔性:語法更直觀,降低了程式碼的開發與閱讀成本。
- 避免覆蓋風險:
Object.hasOwn()
直接作用於Object
,不依賴於物件本身的方法,因此即使物件覆蓋了hasOwnProperty
,它依然可以正常運作。
然而,當我運行程式碼時,卻出現了這樣的錯誤:
1 | TypeError: Object.hasOwn is not a function |
經過調查,我發現這是因為我的專案環境僅支援較早版本的 JavaScript,甚至早到不支援 ES6。這正是導致 Object.hasOwn()
無法運行的原因。
尋找替代方案
既然 Object.hasOwn()
在我們的開發環境中無法使用,我們就需要尋找其他方法來檢查物件的屬性。
在 JavaScript 中,有幾種方法可以用來檢查物件是否擁有某個自有屬性,其中以下兩種是常用的做法:
方法一:直接使用 hasOwnProperty
1 | // 直接在物件上呼叫 hasOwnProperty 方法 |
這是最直覺的寫法,就像是這樣使用:
1 | const tableData = { |
方法二:使用 Object.prototype 的 call 方法
1 | // 透過 Object.prototype 來呼叫 hasOwnProperty |
這種寫法看起來比較複雜,但是更安全。舉例來說:
1 | const tableData = Object.create(null); // 創建一個沒有原型的物件 |
在 JavaScript 中,有時候我們會遇到:
- 使用
Object.create(null)
創建的物件:這種物件沒有繼承任何方法,包括hasOwnProperty
- 有人可能不小心覆蓋了原本的
hasOwnProperty
方法:
1 | const tableData = { |
最終解決方案
考慮到安全性和相容性,我最終選擇了這個解決方案:
1 | // 原始資料 |
這個方法有幾個優點:
- 高度相容:可以在幾乎所有的 JavaScript 環境中運行
- 安全:即使
columnsMap
覆蓋了hasOwnProperty
方法,也能正常工作 - 可靠:不依賴於物件是否繼承自
Object.prototype
何時使用較簡單的方法
儘管我選擇了更安全的方法,但在某些情況下,使用 columnsMap.hasOwnProperty(columnKey)
也是可以接受的:
- 在完全可控的封閉開發環境中
- 單人或小團隊專案,團隊成員都了解潛在風險
- 效能關鍵的應用,需要處理大量數據
從這次專案學習到
這次經歷讓我學到了幾個重要的觀念:
- 始終考慮目標環境的相容性
- 不要忽視安全性,即使是在看似簡單的操作中
- 閱讀文件和社群最佳實踐可以幫助避免潛在問題
結論
雖然新的 JavaScript 特性如 Object.hasOwn()
提供了更簡潔和直觀的語法,但在處理需要廣泛相容性的專案時,使用經過時間考驗的方法如 Object.prototype.hasOwnProperty.call()
可能是更好的選擇。這不僅確保了程式碼在各種環境中的正常運行,還提供了額外的安全性保障。
作為開發者,我們需要在新特性的便利性和程式碼的相容性之間找到平衡。希望這篇文章能幫助其他開發者在遇到類似情況時,做出更好的選擇。