JS判斷數(shù)據(jù)類(lèi)型


在JS中,數(shù)據(jù)類(lèi)型包括

  • 基礎(chǔ)類(lèi)型(String、Number、Boolean、Undefined、Null )
  • 引用類(lèi)型(除 Object 外,還包括 Function 、Array、RegExp、Date 等)

1. typeof

簡(jiǎn)記為
a.對(duì)于基本類(lèi)型,除null外,其他返回值都有效
b.對(duì)于引用類(lèi)型,除function返回值有效為function,其他都返回object
c.null返回值為"object"

2. instanceof

instanceof檢測(cè)對(duì)象在其原型鏈上是否能找到構(gòu)造函數(shù)的prototype屬性

我們用一段偽代碼來(lái)表示一下instanceof

instanceof(object,constructor){
  if(object._proto_===constructor.prototype){
    return true
  }else{
    return false;
  }
}

來(lái)舉些例子


{} instanceof Object;//true
new Date() instanceof Date;//true
 
function Person(){};
new Person() instanceof Person;

[] instanceof Array; //true
[] instanceof Object; //true

我們發(fā)現(xiàn),雖然 instanceof 能夠判斷出 [ ] 是Array的實(shí)例,但它認(rèn)為 [ ] 也是Object的實(shí)例,為什么呢?

我們來(lái)分析一下 [ ]、Array、Object 三者之間的關(guān)系:

從 instanceof 能夠判斷出 [ ].proto 指向 Array.prototype,而 Array.prototype.proto 又指向了Object.prototype,最終 Object.prototype.proto 指向了null,標(biāo)志著原型鏈的結(jié)束。因此,[]、Array、Object 就在內(nèi)部形成了一條原型鏈


從原型鏈可以看出,[] 的 proto 直接指向Array.prototype,間接指向 Object.prototype,所以按照 instanceof 的判斷規(guī)則,[] 就是Object的實(shí)例

3. constructor

當(dāng)一個(gè)函數(shù) F被定義時(shí),JS引擎會(huì)為F添加 prototype 原型,然后再在 prototype上添加一個(gè) constructor 屬性,并讓其指向 F 的引用。如下所示:



當(dāng)執(zhí)行 var f = new F() 時(shí),F(xiàn) 被當(dāng)成了構(gòu)造函數(shù),f 是F的實(shí)例對(duì)象,此時(shí) F 原型上的 constructor 傳遞到了 f 上,因此 f.constructor == F



可以看出,F(xiàn) 利用原型對(duì)象上的 constructor 引用了自身,當(dāng) F 作為構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象時(shí),原型上的 constructor 就被遺傳到了新創(chuàng)建的對(duì)象上, 從原型鏈角度講,構(gòu)造函數(shù) F 就是新對(duì)象的類(lèi)型

細(xì)節(jié)問(wèn)題

  • null 和 undefined 是無(wú)效的對(duì)象,因此是不會(huì)有 constructor 存在的,這兩種類(lèi)型的數(shù)據(jù)需要通過(guò)其他方式來(lái)判斷。
  • 函數(shù)的 constructor 是不穩(wěn)定的,這個(gè)主要體現(xiàn)在自定義對(duì)象上,當(dāng)開(kāi)發(fā)者重寫(xiě) prototype 后,原有的 constructor 引用會(huì)丟失,constructor 會(huì)默認(rèn)為 Object

為什么變成了 Object?
因?yàn)?prototype 被重新賦值的是一個(gè) { }, { } 是 new Object() 的字面量,因此 new Object() 會(huì)將 Object 原型上的 constructor 傳遞給 { },也就是 Object 本身。
因此,為了規(guī)范開(kāi)發(fā),在重寫(xiě)對(duì)象原型時(shí)一般都需要重新給 constructor 賦值,以保證對(duì)象實(shí)例的類(lèi)型不被篡改。

4. toString

toString 是 Object 原型對(duì)象上的方法,使用 call 來(lái)調(diào)用該方法會(huì)返回調(diào)用者的類(lèi)型字符串,格式為 [object,xxx],xxx 是調(diào)用者的數(shù)據(jù)類(lèi)型,包括:String、Number、Boolean、Undefined、Null、Function、Date、Array、RegExp、Error、HTMLDocument等, 基本上,所有的數(shù)據(jù)類(lèi)型都可以通過(guò)這個(gè)方法獲取到。

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window是全局對(duì)象 global 的引用

為什么所有引用類(lèi)型都會(huì)繼承toString方法

因?yàn)橐妙?lèi)型繼承Object,這個(gè)繼承也是通過(guò)原型鏈實(shí)現(xiàn)的。那就說(shuō)明引用類(lèi)型的原型包含一個(gè)內(nèi)部指針指向Object.prototype

為什么要通過(guò) call 或 apply 來(lái)調(diào)用

按照J(rèn)S原型搜索機(jī)制,其他對(duì)象應(yīng)該也可以直接訪問(wèn)到 Object 的 toString方法,而事實(shí)上,大部分的對(duì)象都實(shí)現(xiàn)了自身的 toString 方法,這樣就可能會(huì)導(dǎo)致 Object 的 toString 被終止查找,因此要用 call/apply 來(lái)強(qiáng)制調(diào)用Object 的 toString

每天都努力一點(diǎn)點(diǎn)
謝謝你看完


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容