別再被坑了! JavaScript型別檢測的最佳實踐

控心つcrazy發表於2024-08-16

別再被坑了! JavaScript型別檢測的最佳實踐

在 JavaScript 中,我們經常需要判斷一個變數的型別。這個需求在程式設計中非常常見,因為不同型別的資料會影響到我們的程式碼邏輯。

JavaScript 提供了幾種方法來檢測資料型別,每種方法都有自己的優缺點。

Object.prototype.toString.call()

這是最萬能的方法。它可以準確識別所有的 JavaScript 內建型別,包括基本型別和複雜型別。不管你給它傳什麼資料,它都能給出一個統一格式的字串,告訴你這個資料到底是什麼型別。

它的原理是呼叫物件內部的 [[Class]] 屬性。這個屬性是隻讀的,不能被改寫,所以非常可靠。

優點:

  • 識別範圍廣,基本型別和複雜型別都能識別
  • 不會受到物件自身的 toString() 方法的影響
  • 返回結果格式統一,方便解析

缺點:

  • 寫起來比較囉嗦
  • 如果是自定義型別,只能得到 [object Object],不能進一步區分型別
function detectType(data) {
    return Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
}

console.log(detectType(123)); // 'number'
console.log(detectType('abc')); // 'string'
console.log(detectType(true)); // 'boolean'
console.log(detectType(null)); // 'null'
console.log(detectType(undefined)); // 'undefined'
console.log(detectType([])); // 'array'
console.log(detectType({})); // 'object'
console.log(detectType(function () {})); // 'function'
console.log(detectType(new Date())); // 'date'
console.log(detectType(new RegExp())); // 'regexp'
console.log(detectType(new Error())); // 'error'

typeof

這個運算子最常用,寫起來簡單。它可以識別基本型別和函式,但對複雜型別的識別能力有限。

優點:

  • 使用簡單
  • 可以識別基本型別和函式

缺點:

  • 無法區分陣列和普通物件
  • typeof null 的結果是 'object'
  • 無法識別內建物件型別,如 DateRegExp
console.log(typeof 123); // 'number'
console.log(typeof 'abc'); // 'string'
console.log(typeof true); // 'boolean'
console.log(typeof undefined); // 'undefined'
console.log(typeof null); // 'object' (這是一個歷史遺留的 bug)
console.log(typeof []); // 'object'
console.log(typeof {}); // 'object'
console.log(typeof function () {}); // 'function'

instanceof

instanceof 運算子用於測試建構函式的 prototype 屬性是否出現在物件的原型鏈中的任何位置。

優點:

  • 可以檢查物件是否屬於特定的類或建構函式

缺點:

  • 只能檢查物件型別,不能檢查基本型別
  • 要識別多種型別,需要多次呼叫
console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
console.log(function () {} instanceof Function); // true
console.log(new Date() instanceof Date); // true
console.log(new RegExp() instanceof RegExp); // true
console.log(new Error() instanceof Error); // true

console.log(123 instanceof Number); // false
console.log('abc' instanceof String); // false
console.log(true instanceof Boolean); // false

constructor

constructor 是物件的一個屬性,指向建立該物件的建構函式。可以用它來判斷物件的型別。

優點:

  • 可以識別大多數物件型別,包括自定義型別

缺點:

  • 如果物件的 constructor 屬性被修改,會得到錯誤結果
  • nullundefined 沒有 constructor 屬性
console.log((123).constructor === Number); // true
console.log('abc'.constructor === String); // true
console.log(true.constructor === Boolean); // true
console.log([].constructor === Array); // true
console.log({}.constructor === Object); // true
console.log(function () {}.constructor === Function); // true
console.log(new Date().constructor === Date); // true
console.log(new RegExp().constructor === RegExp); // true
console.log(new Error().constructor === Error); // true

總結

如果需要全面準確的型別識別,Object.prototype.toString.call() 是最佳選擇。
如果只需要簡單區分基本型別,typeof 就足夠了。
如果要檢查物件是否屬於特定型別,可以用 instanceof

在實際應用中,我們可以根據具體需求選擇合適的方法。

結語

上次我開發了一個工具,可以批次清理無用的倉庫。如果你感興趣,可以去看看哦!😊

介紹文章https://mp.weixin.qq.com/s/t7lgc6b7xJiNhfm5vWo5-A

GitHub 倉庫地址https://github.com/yaolife ng0629/del-repos

如果你覺得這個工具對你有所幫助,請不要忘記給我的 GitHub 倉庫 點個 Star ⭐!你的支援是我前進的動力!

感謝閱讀,我們下次再見!

相關文章