在javascript中,咱們判斷一個變量的類型常常用的是typeof來判斷number, string, object, boolean, function, undefined, symbol(es6新增數據類型,我還沒用到過) 這七種類型;在判斷基本數據類型的時候,能告訴咱們具體是哪一種類型,可是在判斷引用類型的時候,好比object,不能肯定的告訴咱們具體是哪一種數據類型,如:javascript
function Person() {
}
var p = new Person();
console.log(typeof p === 'object'); //true
console.log(p instanceof Person); //true複製代碼
在用typeof判斷的時候,只會告訴咱們是object,而不會告訴咱們具體是哪一種object,有一個特例就是 typeof null === ''object'' 返回true ;因此在判斷具體是哪一種object類型的時候都是用instanceof 來判斷,先說說typeof原理:java
在 javascript 的最第一版本中,使用的 32 位系統,爲了性能考慮使用低位存儲了變量的類型信息:es6
有 2 個值比較特殊:bash
typeof null === 'object';
null instanceof Object === false複製代碼
可是ide
null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object複製代碼
這是js歷史遺留的一個bug 因此null也成爲 "薛定諤的對象";函數
所以在用 typeof 來判斷變量類型的時候,咱們須要注意,最好是用 typeof 來判斷基本數據類型(包括symbol),避免對 null 的判斷;
性能
在MDN官方文檔中是這樣介紹的測試
instanceof運算符用於測試構造函數的prototype屬性是否出如今對象的原型鏈中的任何位置
// 定義構造函數
function C(){}
function D(){}
var o = new C();
o instanceof C; // true,由於 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false,由於 D.prototype不在o的原型鏈上
o instanceof Object; // true,由於Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype指向了一個空對象,這個空對象不在o的原型鏈上.
D.prototype = new C(); // 繼承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 由於C.prototype如今在o3的原型鏈上複製代碼
根據instanceof的檢測原理,咱們能夠實現一個自定義的myInstanceofui
function Person() {
}
var p = new Person();
function myInstanceof(l, r) {
let rValue = r.prototype; // 取右表達式的 prototype 值
let lValue = l.__proto__; // 取左表達式的__proto__值
//對待檢測的對象原型進行遍歷
while (true) {
if (lValue === null) {
return false;
}
if (lValue === rValue) {
return true;
}
lValue = lValue.__proto__;
}
}
console.log(myInstanceof(p,Person)); //true
console.log(myInstanceof(p,Object)); //true console.log(myInstanceof(p,Array)); //false 複製代碼
還有一個不錯的判斷類型的方法,就是Object.prototype.toString,咱們能夠利用這個方法來對一個變量的類型來進行比較準確的判斷
spa
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('helloworld') // "[object String]"
Object.prototype.toString.call({a:'hello world'}) // "[object Object]"
Object.prototype.toString.call([1,'a',false]) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"複製代碼
這裏我將這個方法封裝成一個函數,可參考使用:
var isType = (function () {
var types = {};
var t = ['Array','String','Number'];
for(var i = 0;i<t.length;i++){
(function (type) {
types['is'+type] = function (obj) {
return Object.prototype.toString.call(obj) === '[object '+type+']';
}
})(t[i])
}
return types;
})();
isType.isArray([]); //true複製代碼