為什麼不建議直接使用 hasOwnProperty?

圖源網路

前言

這一篇稍微記錄一下為什麼 ESLint 規則會建議不要直接使用 hasOwnProperty

obj.hasOwnProperty

首先我們先認識一下 hasOwnProperty 是什麼,hasOwnProperty 主要是用於檢查一個物件內是否有某個屬性存在,如果有就會回傳 true,反之則會回傳 false,而它的使用方式非常簡單

1
obj.hasOwnProperty('key')

就是如此的簡單,可是這樣的寫法有什麼問題呢?首先當你替專案加上 ESLint 後,你會收到這個錯誤訊息

1
Do not access Object.prototype method 'hasOwnProperty' from target object.

接著當你點下這個連結之後你可以看到 ESLint 建議你改用 Object.prototype.hasOwnProperty.call(obj, 'key') 來取代 obj.hasOwnProperty('key'),這是為什麼呢?

這時候讓我們來看一段範例程式碼吧

1
2
3
4
5
6
7
const obj = {
a: 1,
b: 2,
c: 3,
}

console.log(obj.hasOwnProperty('a')) // true

在一般狀況下,這一段程式碼沒有什麼太大問題,接下來我們刻意在 obj 中加入一個 hasOwnProperty 的屬性,並強制它回傳 false,看看會發生什麼事情

1
2
3
4
5
6
7
8
9
10
const obj = {
a: 1,
b: 2,
c: 3,
hasOwnProperty(){
return false
},
}

console.log(obj.hasOwnProperty('a')) // false

好的,有趣了,為什麼會發生這種問題呢?原因其實是因為 JavaScript 並沒有將 hasOwnProperty 設置為敏感、關鍵字,因此當物件屬性內有相同名稱時,它就會優先使用物件內的屬性,而不是位於原型鏈上的 hasOwnProperty,這就是為什麼 ESLint 會建議你使用 Object.prototype.hasOwnProperty.call(obj, 'key') 來取代 obj.hasOwnProperty('key'),主要是確保你的程式碼不會被意外覆蓋掉。

因此上方正確的寫法為這樣

1
2
3
4
5
6
7
8
9
10
const obj = {
a: 1,
b: 2,
c: 3,
hasOwnProperty(){
return false
},
};

console.log(Object.prototype.hasOwnProperty.call(obj, 'a')); // true

當然,並不是只有 hasOwnProperty 會有這種問題,例如…toString 也會有一樣的狀況

1
2
3
4
5
6
7
8
9
10
const obj = {
a: 1,
b: 2,
c: 3,
toString(){
return 'toString'
},
};

console.log(obj.toString()); // toString

以上來程式碼來講,正確的用法會是這樣

1
2
3
4
5
6
7
8
9
10
const obj = {
a: 1,
b: 2,
c: 3,
toString(){
return 'toString'
},
};

console.log(Object.prototype.toString.call(obj)); // [object Object]

所以其實 ESLint 給予的規範建議都是有它的道理,假設你的專案還沒有開啟 ESLint,那麼我建議你可以先開啟 ESLint,並且遵守它的規範,這樣可以避免一些不必要的問題唷。

(請不要使用這個技巧去惡整你的同事,這樣會讓你的同事很不開心的。)

參考資料

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ