JS資料型別分類和判斷

李趙同學猛猛噠發表於2018-06-21

在前端筆試面試中“JS資料型別的分類和判斷”是高頻的基礎考點,今天總結一下,對正在準備找工作的小夥伴應該有所幫助~

JavaScript中有6種資料型別:數字(number)、字串(string)、布林值(boolean)、undefined、null、物件(Object)。其中物件型別包括:陣列(Array)、函式(Function)、還有兩個特殊的物件:正則(RegExp)和日期(Date)。

一、分類

從不同的角度對6種資料型別進行分類:

JS資料型別分類和判斷

二、判斷

1、typeof

typeof返回一個表示資料型別的字串,返回結果包括:number、string、boolean、object、undefined、function。typeof可以對基本型別number、string  、boolean、undefined做出準確的判斷(null除外,typeof null===“object”,這是由於歷史的原因,我就不巴拉巴拉了,其實我也說不清楚?);而對於引用型別,除了function之外返回的都是object。但當我們需要知道某個物件的具體型別時,typeof就顯得有些力不從心了。

typeof 1; // number 有效
typeof ‘ ’;//string 有效
typeof true; //boolean 有效
typeof undefined; //undefined 有效
typeof null; //object 無效
typeof new Function(); // function 有效
typeof [] ; //object 無效
typeof new Date(); //object 無效
typeof new RegExp(); //object 無效
複製程式碼

2、instanceof

當我們需要知道某個物件的具體型別時,可以用運算子 instanceof,instanceof操作符判斷左運算元物件的原型鏈上是否有右邊這個建構函式的prototype屬性,也就是說指定物件是否是某個建構函式的例項,最後返回布林值。 檢測的我們用一段虛擬碼來模擬instanceof內部執行過程:

instanceof (A,B) = {
    var L = A.__proto__;
    var R = B.prototype;
    if(L === R) {
        //A的內部屬性__proto__指向B的原型物件
        return true;
    }
    return false;
}
複製程式碼

從上述過程可以看出,當 A 的 __proto__ 指向 B 的 prototype 時,就認為A就是B的例項,我們再來看幾個例子:

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

複製程式碼

我們發現,雖然 instanceof 能夠判斷出 [] 是Array的例項,但它認為 [] 也是Object的例項,為什麼呢? 我們來分析一下[]、Array、Object 三者之間的關係: 從instanceof 能夠判斷出 [].__proto__ 指向 Array.prototype, 而 Array.prototype.__proto__ 又指向了Object.prototype,Object.prototype.__proto__ 指向了null,標誌著原型鏈的結束。因此,[]、Array、Object就形成了如下圖所示的一條原型鏈:

JS資料型別分類和判斷

從原型鏈可以看出,[] 的 __proto__  直接指向Array.prototype, 間接指向Object.prototype, 所以按照 instanceof 的判斷規則,[] 就是Object的例項。

注意:instanceof運算子只能用於物件,不適用原始型別的值。

'hello' instanceof String // false
null instanceof Object // false
undefined instanceof Object // false
複製程式碼

字串、null和undefined不是物件,所以返回false。

3、constructor

constructor屬性的作用是,可以得知某個例項物件,到底是哪一個建構函式產生的。

var f = new F();
f.constructor === F;// true
複製程式碼

但是 constructor 屬性易變,不可信賴,這個主要體現在自定義物件上,當開發者重寫prototype後,原有的constructor會丟失。

function F() {}
F.prototype = {
	_name: 'Eric',
};
var f = new F();
f.constructor === F; // false

複製程式碼

因此,為了規範,在重寫物件原型時一般都需要重新給constructor賦值,以保證例項物件的型別不被改寫。

function F() {}
F.prototype = {
    constructor: F, 
   _name: 'Eric',
};
var f = new F();
f.constructor === F; // true 
複製程式碼

4、Object.prototype.toString 

toString是Object原型物件上的一個方法,該方法預設返回其呼叫者的具體型別,更嚴格的講,是 toString執行時this指向的物件型別, 返回的型別格式為[object,xxx],xxx是具體的資料型別,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,... 基本上所有物件的型別都可以通過這個方法獲取到。

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
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 Window]

複製程式碼

需要注意的是,必須通過Object.prototype.toString.call來獲取,而不能直接 new Date().toString(), 從原型鏈的角度講,所有物件的原型鏈最終都指向了Object, 按照JS變數查詢規則,其他物件應該也可以直接訪問到Object的toString方法,而事實上,大部分的物件都實現了自身的toString方法,這樣就可能會導致Object的toString被終止查詢,因此要用call來強制執行Object的toString方法。

三、總結:

typeof可以準確地判斷出基本型別,但是對於引用型別除function之外返回的都是object;

已知是引用型別的情況可以選用instanceof或constructor方法進行具體型別的判斷:

instanceof是基於原型鏈的;

constructor 屬性易變,不可信賴,為了規範,在重寫物件原型時一般都需要重新給constructor賦值,以保證例項物件的型別不被改寫;

Object.prototype.toString.call() 通用但很繁瑣。

感謝您花時間讀到這裡~

按照慣例,推廣一下微信公眾號“前端麻辣燙”,主要是分享前端知識,著重前端筆試面試知識。歡迎關注~歡迎投稿~

微信搜尋微訊號:WebSnacks, 或者微信掃碼關注哦!

JS資料型別分類和判斷

相關文章