在前端筆試面試中「JS數據類型的分類和判斷」是高頻的基礎考點,今天總結一下,對正在準備找工做的小夥伴應該有所幫助~ 前端
JavaScript中有6種數據類型:數字(number)、字符串(string)、布爾值(boolean)、undefined、null、對象(Object)。其中對象類型包括:數組(Array)、函數(Function)、還有兩個特殊的對象:正則(RegExp)和日期(Date)。面試
從不一樣的角度對6種數據類型進行分類: 數組
typeof返回一個表示數據類型的字符串,返回結果包括:number、string、boolean、object、undefined、function。typeof能夠對基本類型number、string 、boolean、undefined作出準確的判斷(null除外,typeof null===「object」,這是因爲歷史的緣由,我就不巴拉巴拉了,其實我也說不清楚😢);而對於引用類型,除了function以外返回的都是object。但當咱們須要知道某個對象的具體類型時,typeof就顯得有些力不從心了。 bash
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 無效
複製代碼
當咱們須要知道某個對象的具體類型時,能夠用運算符 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就造成了以下圖所示的一條原型鏈: ui
從原型鏈能夠看出,[] 的 __proto__ 直接指向Array.prototype, 間接指向Object.prototype, 因此按照 instanceof 的判斷規則,[] 就是Object的實例。this
注意:instanceof運算符只能用於對象,不適用原始類型的值。spa
'hello' instanceof String // false
null instanceof Object // false
undefined instanceof Object // false
複製代碼
字符串、null和undefined不是對象,因此返回false。 prototype
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
複製代碼
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, 或者微信掃碼關注哦!