JavaScript類型檢測(cè)之typeof 和 instanceof 的缺陷與優(yōu)化
在javascript中,typeof 和 instanceof 是用來判斷數(shù)據(jù)類型比較通用的兩個(gè)方法,這篇文章的目的是通過對(duì)這兩個(gè)方法介紹來分析其存在的不足并提出優(yōu)化方案。
typeof
--------------------------------------------------------------------------------
typeof 返回一個(gè)表達(dá)式的數(shù)據(jù)類型的字符串,返回結(jié)果為javascript中的基本數(shù)據(jù)類型,包括:number、boolean、string、object、undefined、function等6種數(shù)據(jù)類型。
typeof 100; //number
typeof (1==1); //boolean
typeof 'onepixel'; //string
typeof {} ; //object
typeof onepixel; // undefined
typeof parseInt; // function
typeof [];//object
typeof new Date(); //object
可以看出,typeof 可以準(zhǔn)確的判斷除object以外的基礎(chǔ)數(shù)據(jù)類型,但不能區(qū)分object類型的具體類型,比如 Array 、Date 以及自定義類。
instanceof
--------------------------------------------------------------------------------
instanceof 本意是用來判斷 A 是否為 B 的實(shí)例對(duì)象,表達(dá)式為:A instanceof B,如果A是B的實(shí)例,則返回true,否則返回false。 在這里需要特別注意的是:instanceof檢測(cè)的是原型,那它是怎么檢測(cè)的呢,我們用一段偽代碼來模擬其內(nèi)部執(zhí)行過程:
instanceof (A,B) = {
var L = A.__proto__;
var R = B.prototype;
if(L === R) {
//A的內(nèi)部屬性__proto__指向B的原型對(duì)象
return true;
}
return false;
}
從上述過程可以看出,當(dāng)A的__proto__ 指向B的prototype時(shí),就認(rèn)為A就是B的實(shí)例對(duì)象,我們?cè)賮砜磶讉€(gè)例子:
[] instanceof Array; //true
{} instanceof Object;//true
new Date() instanceof Date;//true
function Person(){};
new Person() instanceof Person;
[] instanceof Object; //true
new Date() instanceof Object;//tru
new Person instanceof Object;//true
從上面的例子中,我們發(fā)現(xiàn)雖然instanceof能夠正確判斷[] 是Array的實(shí)例對(duì)象,但不能辨別 [] 不是Object的實(shí)例對(duì)象,為什么呢,這還需要從javascript的原型鏈說起,我們首先來分析一下[]、Array、Object 三者之間的關(guān)系,從instanceof判斷能夠得出:[].__proto__ ->Array.prototype, 而Array.prototype.__proto__指向了Object.prototype,Object.prototype.__proto__ 指向了null,標(biāo)志著原型鏈的結(jié)束。(ps:關(guān)于JS原型鏈請(qǐng)閱讀:淺談javascript原型和原型鏈) 因此,[]、Array、Object就形成了一條原型鏈:

從原型鏈可以看出,[]的__proto__最終指向了Object.prototype,類似的new Date()、new Person() 也會(huì)形成這樣一條原型鏈,因此,我們用 instanceof 也不能完全精確的判斷object類的具體數(shù)據(jù)類型。
優(yōu)化方案
--------------------------------------------------------------------------------
對(duì)于這個(gè)問題,在閱讀jQuery源碼時(shí),發(fā)現(xiàn)了一個(gè)比較好的解決方案,由于源碼之間存在相互調(diào)用不便于閱讀和理解,因此,按照其思路進(jìn)行了整理和封裝,代碼如下:
(function(){
var class2type = {};
var typeList = "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " );
typeList.eachEach(function(item){
class2type[ "[object " + item + "]" ] = item.toLowerCase();
}
return {
getObjType:function(obj) {
if ( obj == null ) {
return obj + "";
}
if(typeof obj === "object" || typeof obj === "function"){
class2type[ toString.call( obj ) ] || "object"
}else {
return typeof obj;
}
}
}
})()
JavaScript 中 typeof 和 instanceof 常用來判斷一個(gè)變量是否為空,或者是什么類型的。但它們之間還是有區(qū)別的:
typeof
typeof 是一個(gè)一元運(yùn)算,放在一個(gè)運(yùn)算數(shù)之前,運(yùn)算數(shù)可以是任意類型。
它返回值是一個(gè)字符串,該字符串說明運(yùn)算數(shù)的類型。typeof 一般只能返回如下幾個(gè)結(jié)果:
number,boolean,string,function,object,undefined。我們可以使用 typeof 來獲取一個(gè)變量是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因?yàn)槿绻?a 不存在(未聲明)則會(huì)出錯(cuò),對(duì)于 Array,Null 等特殊對(duì)象使用 typeof 一律返回 object,這正是 typeof 的局限性。
網(wǎng)上的一個(gè)小例子:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="javascript" type="text/javascript">
document.write ("typeof(1): "+typeof(1)+"<br>");
document.write ("typeof(NaN): "+typeof(NaN)+"<br>");
document.write ("typeof(Number.MIN_VALUE): "+typeof(Number.MIN_VALUE)+"<br>");
document.write ("typeof(Infinity): "+typeof(Infinity)+"<br>");
document.write ("typeof(\"123\"): "+typeof("123")+"<br>");
document.write ("typeof(true): "+typeof(true)+"<br>");
document.write ("typeof(window): "+typeof(window)+"<br>");
document.write ("typeof(Array()): "+typeof(new Array())+"<br>");
document.write ("typeof(function(){}): "+typeof(function(){})+"<br>");
document.write ("typeof(document): "+typeof(document)+"<br>");
document.write ("typeof(null): "+typeof(null)+"<br>");
document.write ("typeof(eval): "+typeof(eval)+"<br>");
document.write ("typeof(Date): "+typeof(Date)+"<br>");
document.write ("typeof(sss): "+typeof(sss)+"<br>");
document.write ("typeof(undefined): "+typeof(undefined)+"<br>")
</script>
<title>javascript類型測(cè)試</title>
</head>
<body>
</body>
</html>
instanceof
instance:實(shí)例,例子
a instanceof b?alert("true"):alert("false"); //a是b的實(shí)例?真:假
instanceof 用于判斷一個(gè)變量是否某個(gè)對(duì)象的實(shí)例,如 var a=new Array();alert(a instanceof Array); 會(huì)返回 true,同時(shí) alert(a instanceof Object) 也會(huì)返回 true;這是因?yàn)?Array 是 object 的子類。再如:function test(){};var a=new test();alert(a instanceof test) 會(huì)返回
談到 instanceof 我們要多插入一個(gè)問題,就是 function 的 arguments,我們大家也許都認(rèn)為 arguments 是一個(gè) Array,但如果使用 instaceof 去測(cè)試會(huì)發(fā)現(xiàn) arguments 不是一個(gè) Array 對(duì)象,盡管看起來很像。
另外:
測(cè)試 var a=new Array();if (a instanceof Object) alert('Y');else alert('N');
得'Y'
但 if (window instanceof Object) alert('Y');else alert('N');
得'N'
所以,這里的 instanceof 測(cè)試的 object 是指 js 語法中的 object,不是指 dom 模型對(duì)象。
使用 typeof 會(huì)有些區(qū)別
alert(typeof(window)) 會(huì)得 object
大家知道JavaScript中判斷函數(shù)參數(shù)類型是用typeof還是instanceof嗎?
typeof只能判斷js已有的幾個(gè)類型,如function,object,number。
而instanceof可以判斷對(duì)象是由哪個(gè)函數(shù)實(shí)例化出來的,如:
var a=function(x){};
var b=function(x){};
var c=new a(1);
var d=new a(2);
c instanceof a為true而d instanceof b為false。
而用typeof c和typeof d的結(jié)果都是object
“判斷函數(shù)參數(shù)類型”需要根據(jù)你的需求來選擇用哪個(gè)。
相關(guān)文章
JavaScript圖像放大鏡效果實(shí)現(xiàn)方法詳解
這篇文章主要介紹了JavaScript圖像放大鏡效果實(shí)現(xiàn)方法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
js實(shí)現(xiàn)數(shù)組去重方法及效率對(duì)比
本文主要介紹了js實(shí)現(xiàn)數(shù)組去重方法及效率對(duì)比。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02
Bootstrap模態(tài)對(duì)話框中顯示動(dòng)態(tài)內(nèi)容的方法
今天小編就為大家分享一篇Bootstrap模態(tài)對(duì)話框中顯示動(dòng)態(tài)內(nèi)容的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08
Javascript和HTML5利用canvas構(gòu)建Web五子棋游戲?qū)崿F(xiàn)算法
這只是一個(gè)簡(jiǎn)單的JAVAscript和HTML5小程序,沒有實(shí)現(xiàn)人機(jī)對(duì)戰(zhàn),五子棋棋盤落子點(diǎn)對(duì)應(yīng)的二維數(shù)組,具體的實(shí)現(xiàn)算法如下,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助2013-07-07
微信小程序swiper實(shí)現(xiàn)滑動(dòng)放大縮小效果
這篇文章主要介紹了微信小程序swiper實(shí)現(xiàn)滑動(dòng)放大縮小效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11
使用JSON格式提交數(shù)據(jù)到服務(wù)端的實(shí)例代碼
這篇文章主要介紹了使用JSON格式提交數(shù)據(jù)到服務(wù)端的實(shí)例代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2018-04-04
理解javascript定時(shí)器中的setTimeout與setInterval
這篇文章主要幫助大家學(xué)習(xí)理解javascript定時(shí)器中的setTimeout與setInterval,從實(shí)例出發(fā)進(jìn)行深入探討,感興趣的小伙伴們可以參考一下2016-02-02

