別再被坑了! JavaScript類(lèi)型檢測(cè)的最佳實(shí)踐
在 JavaScript 中,我們經(jīng)常需要判斷一個(gè)變量的類(lèi)型弯淘。這個(gè)需求在編程中非常常見(jiàn),因?yàn)椴煌?lèi)型的數(shù)據(jù)會(huì)影響到我們的代碼邏輯。
JavaScript 提供了幾種方法來(lái)檢測(cè)數(shù)據(jù)類(lèi)型,每種方法都有自己的優(yōu)缺點(diǎn)璃搜。
Object.prototype.toString.call()
這是最萬(wàn)能的方法。它可以準(zhǔn)確識(shí)別所有的 JavaScript 內(nèi)置類(lèi)型,包括基本類(lèi)型和復(fù)雜類(lèi)型鳞上。不管你給它傳什么數(shù)據(jù),它都能給出一個(gè)統(tǒng)一格式的字符串,告訴你這個(gè)數(shù)據(jù)到底是什么類(lèi)型这吻。
它的原理是調(diào)用對(duì)象內(nèi)部的 [[Class]]
屬性。這個(gè)屬性是只讀的,不能被改寫(xiě),所以非掣菀椋可靠唾糯。
優(yōu)點(diǎn):
- 識(shí)別范圍廣,基本類(lèi)型和復(fù)雜類(lèi)型都能識(shí)別
- 不會(huì)受到對(duì)象自身的
toString()
方法的影響 - 返回結(jié)果格式統(tǒng)一,方便解析
缺點(diǎn):
- 寫(xiě)起來(lái)比較啰嗦
- 如果是自定義類(lèi)型,只能得到
[object Object]
,不能進(jìn)一步區(qū)分類(lèi)型
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
這個(gè)運(yùn)算符最常用,寫(xiě)起來(lái)簡(jiǎn)單。它可以識(shí)別基本類(lèi)型和函數(shù),但對(duì)復(fù)雜類(lèi)型的識(shí)別能力有限鬼贱。
優(yōu)點(diǎn):
- 使用簡(jiǎn)單
- 可以識(shí)別基本類(lèi)型和函數(shù)
缺點(diǎn):
- 無(wú)法區(qū)分?jǐn)?shù)組和普通對(duì)象
-
typeof null
的結(jié)果是'object'
- 無(wú)法識(shí)別內(nèi)置對(duì)象類(lèi)型,如
Date
移怯、RegExp
等
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' (這是一個(gè)歷史遺留的 bug)
console.log(typeof []); // 'object'
console.log(typeof {}); // 'object'
console.log(typeof function () {}); // 'function'
instanceof
instanceof
運(yùn)算符用于測(cè)試構(gòu)造函數(shù)的 prototype
屬性是否出現(xiàn)在對(duì)象的原型鏈中的任何位置。
優(yōu)點(diǎn):
- 可以檢查對(duì)象是否屬于特定的類(lèi)或構(gòu)造函數(shù)
缺點(diǎn):
- 只能檢查對(duì)象類(lèi)型,不能檢查基本類(lèi)型
- 要識(shí)別多種類(lèi)型,需要多次調(diào)用
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
是對(duì)象的一個(gè)屬性,指向創(chuàng)建該對(duì)象的構(gòu)造函數(shù)这难≈畚螅可以用它來(lái)判斷對(duì)象的類(lèi)型。
優(yōu)點(diǎn):
- 可以識(shí)別大多數(shù)對(duì)象類(lèi)型,包括自定義類(lèi)型
缺點(diǎn):
- 如果對(duì)象的
constructor
屬性被修改,會(huì)得到錯(cuò)誤結(jié)果 -
null
和undefined
沒(méi)有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
總結(jié)
如果需要全面準(zhǔn)確的類(lèi)型識(shí)別,Object.prototype.toString.call()
是最佳選擇雁佳。
如果只需要簡(jiǎn)單區(qū)分基本類(lèi)型,typeof
就足夠了脐帝。
如果要檢查對(duì)象是否屬于特定類(lèi)型,可以用 instanceof
。
在實(shí)際應(yīng)用中,我們可以根據(jù)具體需求選擇合適的方法糖权。
結(jié)語(yǔ)
上次我開(kāi)發(fā)了一個(gè)工具堵腹,可以批量清理無(wú)用的倉(cāng)庫(kù)。如果你感興趣星澳,可以去看看哦疚顷!??
介紹文章: https://mp.weixin.qq.com/s/t7lgc6b7xJiNhfm5vWo5-A
GitHub 倉(cāng)庫(kù)地址: https://github.com/yaolife ng0629/del-repos
如果你覺(jué)得這個(gè)工具對(duì)你有所幫助,請(qǐng)不要忘記給我的 GitHub 倉(cāng)庫(kù) 點(diǎn)個(gè) Star ?!你的支持是我前進(jìn)的動(dòng)力腿堤!
感謝閱讀阀坏,我們下次再見(jiàn)!