JS中數據類型的判斷( typeof,instanceof,constructor,Object.prototype.toString.call()區別)

js判斷數據類型很有多種方法,下面主要說下 typeof,instanceof,constructor,Object.prototype.toString.call()區別!

1.typeof

這個最熟悉不過了,判斷數據類型很常用的方法!但是它都能判斷什麼數據類型呢?

console.log(typeof 2);//number
console.log(typeof "2");//string
console.log(typeof true);//boolean
console.log(typeof undefined);//underfined
console.log(typeof null);//object
console.log(typeof function(){});//Function
console.log(typeof [1,2,3]);//object
console.log(typeof {p:1});//object

很明顯的看出,基本類型除非了null判斷類型是object外,其他的都能很準確的作出判斷,然後引用類型除非了functrion 能夠準備判斷出類型,其他判斷都是object類型!
結論:基本類型可以作出準確判斷(null除外),也不能很準確的判斷出引用類型!

2.instanceof

這個應該見過,但是用的可能不是很多,a instranceof b,意思判斷 b的原型對象是否在a的原型鏈上!
我們來模擬下它的原理!

function instanceOfTest(a, b) {
         var bp = b.prototype;
         var ap = a.__proto__;//在原型鏈上找原型對象
         while (true) {
             if (ap === bp) {// 相等就說明在原型鏈上找到b的原型了
                 return true;
             } else if (ap === null) {//找到盡頭了,確實沒有
                 return false;
             }
             ap = ap.__proto__; //沒找到,一直往上找
         };
     };
console.log(instanceOfTest([], Object)); //true
console.log([] instanceof Object);//true

註釋寫的很清楚,也很直觀的代碼!那麼它能做什麼呢?它可以判斷引用類型,基本類型判斷不了(下面會講原因),先看看怎麼判斷引用類型的

console.log([] instanceof Array);//true
console.log({} instanceof Object);//true
console.log(function(){} instanceof Function);//true

看上去好像沒啥問題,但是如果後面是Object的話,那麼都返回true,因爲Object是它們的祖師爺了!

console.log([] instanceof Object);//true
console.log({} instanceof Object);//true
console.log(function(){} instanceof Object);//true

再來看看基本類型的

var a =1;
console.log(a instanceof Number);//false
console.log(a.constructor === Number);//true

這裏有個坑!其實 a是Number的實例,Number的原型也在a的原型鏈上!爲什麼 a instanceof Number結果是false? 其實是 object instranceof constructor ,注意看!是object,如果不是object全部返false,那麼問題來了?爲什麼實例出來的對象變成了基本類型?很懵!!! 其實當我們字面量創建變量時候,後臺就會創建一個對應的基本包裝類型的對象,下面是它的創建過程!
1.創建String的實例
2.在實例上調用指定的方法
3.銷燬這個實例

var a = "1234" 
//等價於
var a = new Number("1234");
var copyA = a.substr(0);
a = null;

這個過程是非常短暫的,這個也是引用類型和包裝類型的最大區別,也就是對象的生命週期,在運行的一瞬間就被銷燬了,這個也是爲什麼在運行的時候在包裝對象上添加不了屬性和方法

var a = "1234"
a.add = "add";
console.log(a);//underfined

知道了這個原理,那麼上面疑惑也應該解決了!

3.constructor

顧名思義構造函數,肯定是指向構造函數,在原型上纔有這個屬性,由於實例出來的對象會繼承原型上的屬性,所以也有這個屬性

console.log((1).constructor ===Number);//true
console.log(true.constructor === Boolean);//true
console.log("1".constructor === String);//true
console.log([].constructor === Array);//true
console.log(function(){}.constructor === Function);//true
console.log({}.constructor === Object);//true

這裏有一點需要注意,當直接給原型賦值後,那麼constructor指向就會改變!

function A(){

};
var p =new A();
console.log(p.constructor===A);//true
A.prototype = [];
var p1 =new A();
console.log(p1.constructor===A);//false
console.log(p1.constructor===Array);//true
4.Object.prototype.toString.call()

這個是推薦使用的,能夠比較精準的判斷各種類型,原理是借用Object原型上的toString()方法!

var test = Object.prototype.toString;
console.log(test.call(1));//[object Number]
console.log(test.call("1"));//[object String]
console.log(test.call(true));//[object Boolean]
console.log(test.call(function(){}));//[object Function]
console.log(test.call(undefined));//[object Undefined]
console.log(test.call(null));//[object Null]
console.log(test.call([]));//[object Array]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章