JS靈巧判斷7種類型的方式

類型:

JavaScript 中有七種內(nèi)置類型:
  1. 空值 (null)
  2. 未定義 (undefined)
  3. 布爾值 (boolean)
  4. 數(shù)字 (number)
  5. 字符串 (string)
  6. 對(duì)象 (object)
  7. 符號(hào) (symbol赏表,ES6中新增)

在 JS 中呢,有很多坑逛万,本文章將結(jié)合 undersoce.js源碼 和我所總結(jié)的方法準(zhǔn)確判斷這六種類型奠蹬,第七種也會(huì)提供一種判斷思路租漂;

image

先來(lái)一個(gè)小測(cè)試:

首先逐纬,大家都熟悉的一種判斷方式 typeof包个,這是一種雖然老掉牙但是有些實(shí)用的方式 :

typeof null         // "object"         <= 在后面文章里你會(huì)看到垛玻,巨坑!T蠼鳌璧榄!

typeof undefined            // "undefined"

typeof true         // "boolean"

typeof 42               // "number"

typeof "42"         // "string"

typeof {life: 42}               // "object"

typeof Symbol()             // "symbol"


// ------------后面3種是單獨(dú)提出來(lái)的注意事項(xiàng)------------------

typeof void 0              // "undefined"   <= 這是一個(gè)非常實(shí)用的技巧,我將在后面解釋吧雹;

typeof [1,2,3]             // "object"  <= 數(shù)組 其實(shí)也是對(duì)象骨杂,巨坑!P劬怼搓蚪!

typeof function a() { }     // "function" 
image

巧用 “ ! ” 號(hào):

!null              // true             <= 這是一個(gè)非常巧妙的技巧,下面將解釋龙亲;

!undefined         // true             <= 這是一個(gè)非常巧妙的技巧陕凹,下面將解釋悍抑;

------------我們不一樣v!搜骡!------------

!123              // false

!true             // false

!{a: 123}         // false

!function a() { }         // false

!'123'            // false

有了這個(gè)區(qū)別拂盯,我們可以做一些有趣的事情,這是在 undersoce.js 源碼里面學(xué)到的技巧记靡,這樣能夠準(zhǔn)確地排除 null 和 undefined

image

無(wú)敵法 “ .toString.call() ”:

當(dāng)然 Object.prototype.toString.call 也可以換成 Object.prototype.toString.apply 谈竿。

Object.prototype.toString.call(null)        // "[object Null]"

Object.prototype.toString.call(undefined)   // "[object Undefined]"

Object.prototype.toString.call(123)         // "[object Number]"

Object.prototype.toString.call(true)        // "[object Boolean]"

Object.prototype.toString.call('123')       // "[object String]"

Object.prototype.toString.call({a: 123})    // "[object Object]"

Object.prototype.toString.call(Symbol())    // "[object Symbol]"


// ---------------單獨(dú)出來(lái)講的幾個(gè)注意事項(xiàng)---------------------

Object.prototype.toString.call([1,2,3]) // "[object Array]"

Object.prototype.toString.call(function a() { })    // "[object Function]" 其實(shí)函數(shù)也是object類型

Object.prototype.toString.call(new Date)    // "[object Date]"  日期對(duì)象

Object.prototype.toString.call(Math)        // [object Math]    數(shù)學(xué)函數(shù)對(duì)象

Object.prototype.toString.call(function a() { })    // "[object Function]" 其實(shí)函數(shù)也是object類型

注1:這種方式存在兼容性問(wèn)題,具體兼容性問(wèn)題點(diǎn)擊 這里 摸吠,JavaScript 1.8.5空凸,無(wú)法完全檢測(cè)上述情況。

注2:使用這套技巧寸痢,能夠準(zhǔn)確地分辨這7種類型甚至更多更精確呀洲,而 typeof 卻無(wú)法區(qū)分完全!L渲埂5蓝骸!献烦!

image

來(lái)看看 " constructor "吧:

這種方式是判斷對(duì)象的構(gòu)造函數(shù)是誰(shuí)滓窍,至于什么是構(gòu)造函數(shù)我將在另一篇文章寫道;

var n1 = null;
n.constructor             // 報(bào)錯(cuò):因?yàn)?null 是 JS 原型鏈的起點(diǎn)巩那,沒(méi)有構(gòu)造函數(shù)吏夯;

var u = undefined;
u.constructor             // 報(bào)錯(cuò):它也沒(méi)有構(gòu)造函數(shù)此蜈;

var a = [1, 2, 3];
a.constructor === Array;   // true  數(shù)組

var n = 123;
n.constructor === Number;  // true  數(shù)字

var s1 = '123';
abc.constructor === String  // true 字符串

var o = {a: 123};
o.constructor === Object;   // true 對(duì)象

var s = Symbol()
abc.constructor === Symbol  // true 符號(hào)

------------------單獨(dú)出來(lái)講的幾個(gè)注意事項(xiàng)----------------------

var arr = [1, 2, 3];
arr.constructor === Array   // true 數(shù)組 能夠很好地區(qū)分

var fun = function a() { };
fun.constructor === Function  // true 函數(shù)

var abc = new Date();
abc.constructor === Date;    // true 日期 

var abc = new RegExp();
abc.constructor === RegExp; // true 正則 

var abc = Math
abc.constructor === Math;   // false 不可以像Object.prototype.toString.call()一樣區(qū)分;

abc.constructor === Object   // true 事實(shí)上沒(méi)有Math這個(gè)構(gòu)造函數(shù),Math的構(gòu)造函數(shù)在 Object上的

image

最后一招 “ instanceof ”:

注意:使用對(duì)象必須是一個(gè) object 锦亦;

// 語(yǔ)法: object instanceof constructor舶替;

var n1 = 123;            // n 是類型為 Number 的元素!8茉啊顾瞪!不是對(duì)象!E滓稀陈醒!
typeof n1;               // "number"    回想一下我們有7種類型
n1 instanceof Number;     // false   function Number() { }

var n2 = new Number(123)  // 現(xiàn)在 n2 是一個(gè) object 元素!G扑Α钉跷!
typeof n2;               // "object"
n2 instanceof Number;     // true

正如,上述方式所說(shuō)肚逸,這種方式只適合判斷 object R蕖!朦促!

var a = [1, 2, 3];      // 在最開始就聲明了膝晾,數(shù)組也是對(duì)象,此法可以用來(lái)判斷數(shù)組务冕;

a instanceof Array;     // 而這個(gè)對(duì)象的構(gòu)造函數(shù)是 function Array() { }

// 雖然 typeof null 也是 object 但這是最底層的元素

在這里我就不過(guò)多舉例子了血当,你如果不知道原型鏈的東西,那就先記住 instanceof 能判斷數(shù)組吧Y饕洹臊旭!

閱讀聲明:法1都是來(lái)源于 underscore.js 源碼:

空值 (null):

法1:直接用嚴(yán)格等于判斷。
var isNull = function (obj) {
    return obj === null;
};

這是最直接并且有效的方式箩退;

法2:巧妙地利用 ! null 的結(jié)果為 true:
var isNull = function (obj) {
    return !obj && typeof obj === "object";
};

此方法雖然很巧妙离熏,但是沒(méi)有法1直接;

未定義 (undefined)

法1:這是最推薦的方式戴涝。
var isUndefined = function (obj) {
    return obj === void 0;
}

很多常見(jiàn)的工具庫(kù)都采用這種方式滋戳,極力推薦!:袄āk使稀;

法2:直接利用 typeof 判斷:
var isUndefined = function (obj) {
    return typeof obj === "undefined";
}

這種方式郑什,也是相對(duì)穩(wěn)定的府喳;

注意:

  1. 在全局條件下 undefined 是不可以被修改的。
  2. 在局部條件下 undefined 在某種情況下是可以被修改的蘑拯。
  3. 請(qǐng)狠狠地戳這里钝满,看官方文檔解釋兜粘。
(function(undefined) {
   console.log(undefined);        // "123"
})('123')

布爾值 (boolean)

這里其實(shí)我也有疑惑,為什么 underscore.js 會(huì)這樣判斷弯蚜,讀者知道可以聯(lián)系我孔轴;

var toString = Object.prototype.toString;

var isBoolean = function (obj) {
    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
}

類似地,我們采用 .constructor 和 typeof 的方式也可以實(shí)現(xiàn)判斷碎捺。

數(shù)字 (number)

var toString = Object.prototype.toString;

var isNumber = function (obj) {
    return toString.call(obj) === '[object Number]';
}

類似地路鹰,我們采用 constructortypeof 的方式也可以實(shí)現(xiàn)判斷。

字符串 (string)

var toString = Object.prototype.toString;

var isString = function (obj) {
    return toString.call(obj) === '[object String]';
}

類似地收厨,我們采用 constructortypeof 的方式也可以實(shí)現(xiàn)判斷晋柱。

對(duì)象 (object)

var toString = Object.prototype.toString;

var isObject = function (obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
}

這里,是我最疑惑的地方诵叁,為什么要用 !!obj 雁竞?

  1. typeof null === object 結(jié)果為 true ;
  2. 最開始我已經(jīng)講了一種,!obj 的方式拧额,nullundefined 返回結(jié)果都為 true 而其他類型為 false碑诉;
  3. 以上面這種實(shí)現(xiàn)方式,如果傳遞值為 null 的時(shí)候侥锦,就會(huì)被 !!obj 過(guò)濾掉进栽;

或者動(dòng)手試試,將 && !!obj 刪掉捎拯,看看能否達(dá)到預(yù)期效果泪幌。

其他:

其實(shí)上文已經(jīng)給出思路實(shí)現(xiàn)盲厌,Date, Math, RegExp等內(nèi)置對(duì)象署照,我就不詳談了,用得較少:

數(shù)組(Array)

法1: 最穩(wěn)妥的辦法:
Object.prototype.toString.call([1,2,3]) // "[object Array]"

老老實(shí)實(shí)地用這個(gè)方法吧B鸷啤=ㄜ健!

法2:instanceof 法懂扼,僅為拓展:
var a = [1, 2, 3];      // 在最開始就聲明了禁荸,數(shù)組也是對(duì)象,此法可以用來(lái)判斷數(shù)組阀湿;

a instanceof Array;     // 而這個(gè)對(duì)象的構(gòu)造函數(shù)是 function Array() { }
法3:構(gòu)造函數(shù)法赶熟,僅為拓展
var a = [1, 2, 3];
a.constructor === Array;   // true  數(shù)組

注:如果 a = null ,還要報(bào)錯(cuò)陷嘴,這種方式堅(jiān)決不推薦S匙!灾挨!

法4:檢查原型的構(gòu)造函數(shù)邑退,僅為拓展:
var a = [1, 2, 3];

a.__proto__.constructor === Array

其實(shí)法2-4都是屬于一種思路竹宋,判斷這個(gè)對(duì)象的構(gòu)造函數(shù)是否為數(shù)組,僅僅實(shí)現(xiàn)方式不同罷了地技。

參考和鳴謝:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末莫矗,一起剝皮案震驚了整個(gè)濱河市飒硅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌作谚,老刑警劉巖狡相,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異食磕,居然都是意外死亡尽棕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門彬伦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)滔悉,“玉大人,你說(shuō)我怎么就攤上這事单绑』毓伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵搂橙,是天一觀的道長(zhǎng)歉提。 經(jīng)常有香客問(wèn)我,道長(zhǎng)区转,這世上最難降的妖魔是什么苔巨? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮废离,結(jié)果婚禮上侄泽,老公的妹妹穿的比我還像新娘。我一直安慰自己蜻韭,他們只是感情好悼尾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著肖方,像睡著了一般闺魏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上俯画,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天析桥,我揣著相機(jī)與錄音,去河邊找鬼。 笑死烹骨,一個(gè)胖子當(dāng)著我的面吹牛翻伺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播沮焕,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吨岭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了峦树?” 一聲冷哼從身側(cè)響起辣辫,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎魁巩,沒(méi)想到半個(gè)月后急灭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谷遂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年葬馋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肾扰。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡畴嘶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出集晚,到底是詐尸還是另有隱情窗悯,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布偷拔,位于F島的核電站蒋院,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏莲绰。R本人自食惡果不足惜欺旧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钉蒲。 院中可真熱鬧切端,春花似錦彻坛、人聲如沸顷啼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钙蒙。三九已至,卻和暖如春间驮,著一層夾襖步出監(jiān)牢的瞬間躬厌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扛施,地道東北人鸿捧。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像疙渣,于是被迫代替她去往敵國(guó)和親匙奴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容