1. 程式人生 > >JavaScript型別檢測詳解

JavaScript型別檢測詳解

JavaScript型別檢測

本篇介紹一下如何檢測JavaScript各種型別。

• 5種原始型別
• 物件
• Function
• Array
• 屬性

5種原始型別
JavaScript中5種原始型別為string,number,boolean,undefined,null

var name = "Jack";
var age = 32;
var single = false;
var app;    //undefined

console.log(typeof name);   //string
console.log(typeof age);    //number
console
.log(typeof single); //boolean console.log(typeof app); //undefined console.log(typeof null); //object

發現除null外的其他4種基本型別均可以用typeof來識別:

if(typeof name === "string") { name += "Zhang"; }
if(typeof age === "number") { age++; }
if(typeof single === "boolean" && single) { … }
if(typeof app === "undefined"
) { app = {}; }

因為typeof null會得到object,所以直接用===來檢測null:
if(el === null) { … }
物件
JavaScript的物件包括內建物件(Date,RegExp ,Error等)和自定義物件。
(注意,Function和Array雖然也都是內建物件,但下一節單獨講)
物件不能像基本型別那樣用typeof來檢測了,因為檢測出來的結果都是object:

console.log(typeof new Date());    //object
console.log(typeof new RegExp());  //object
console.log(typeof new Error()); //object console.log(typeof new Person()); //用typeof檢測出自定義物件也是object

要改用instanceof來檢測:

var date = new Date();
var reg = new RegExp();
var err = new Error();
var me = new Person();

if(date instanceof Date) {    //檢測日期
    year = date.getFullYear(); 
}
if(reg instanceof RegExp) {    //檢測正則表示式
    reg.test(...); 
}
if(err instanceof Error) {    //檢測異常
    throw err; 
}
if(me instanceof Person) {    //檢測自定義物件
    ... 
}

但自定義物件有個問題,假設瀏覽器frameA裡和frameB裡都定義了Person。 frameA裡定義了me物件,用me instanceof Person檢測出來為true。但當自定義物件me傳給frameB後,在frameB裡instanceof會是false。
本節一開頭就說了,Function和Array雖然也都是內建物件,但留到下一節講。原因就是Function和Array也有和自定義物件相同的上述問題。因此Function和Array一般不用instanceof

Function
上面說了用instanceof檢測Function不能跨frame。因此用typeof來檢測,它可跨frame:
var func = function(){};
if(typeof func === ‘function’) { … }
但IE8以前用typeof來檢測DOM系函式會得到object,因此IE8以前改用in:

console.log(typeof document.getElementById);        //object,不是function
console.log(typeof document.getElementsByTagName);  //object,不是function
console.log(typeof document.createElement);         //object,不是function

//IE8以前的IE瀏覽器,要改用in來檢測是否支援DOM函式

if("getElementById" in document) { … }        
if("getElementsByTagName" in document) { … }
if("createElement" in document) { … }

Array
上面說了用instanceof檢測Array不能跨frame。ES5之前都自定義檢測方法。其中最精確的方法:依賴Array的toString會返回固定字串”[Object Array]”的事實來檢測:

function isArray(arr) {
    return Object.prototype.toString.call(arr) === "[Object Array]";
}

該方法精確且優雅,因此被很多庫所採納,最終在ES5被作為isArray方法引入了Array,參照MDN。現在你不需要自定義檢測方法了,直接用isArray()即可。
其他檢測方法,都各有缺陷,不能100%精確。但作為一種思路是可以借鑑的。例如依賴Array是唯一包含sort方法的物件的事實來檢測:

function isArray(arr) {
    return typeof arr.sort === "function";
}

如果是自定義物件也定義了sort方法,該方法就失效了。
屬性
檢測屬性是否在例項物件中應該用hasOwnProperty。如果你不關心屬性是在例項物件中還是在原型物件中,可以簡單點用in
例如檢測字面量物件屬性:

var Person = {
    name: "Jack",
    age: 33
};
if("name" in Person) { … }                 //true
if(Person.hasOwnProperty("name")) { … }    //true

例如例項物件屬性:

var Person = function (name, age) {
    this.name = name;
    this.age = age;
};
Person.prototype.location = "Shanghai";

var me = new Person("Jack", 33)
if("name" in me) { … }                 //true
if(me.hasOwnProperty("name")) { … }    //true
if("location" in me) { … }             //true
if(me.hasOwnProperty("location")) { … }//false

除此之外其他方法都不好:

if (object[propName])            //Not Good,你怎麼知道屬性值不是0或1?
if (object[propName] === null)        //Not Good,你怎麼知道屬性值不是null?
if (object[propName] === undefined)    //Not Good,你怎麼知道屬性值不是undefined?

總結
**用typeof檢測string,number,boolean,undefined,Function
用===檢測null
用isArray()檢測Array
用instanceof檢測內建物件(除Function和Array)和自定義物件
用hasOwnProperty檢測屬性是否在例項物件中。如果你不關心屬性是在例項物件中還是在原型物件中,可以簡單點用in**

更多資源可以訪問:去轉盤;或者加QQ群一起討論學習js,css等技術(QQ群:512245829)