JS中檢測數據類型的幾種方式及優缺點【轉】

一、typeof 用來檢測數據類型的運算符javascript

typeof value 返回值首先是一個字符串,其次裏面包含了對應的數據類型,例如:"number"、"string"、"boolean"、"undefined"、"object"、"function"html

侷限性:
1)typeof null ->"object"
2)檢測的無論是數組仍是正則都返回的是"object",因此typeof不能判斷一個值是否爲數組
java

1
console.log( typeof  [12, 23]); //->"Object"

 

二、instanceof/constructor數組

檢測某一個實例是否屬於某一個類
使用instanceof/constructor能夠檢測數組和正則閉包

1
2
3
4
5
6
console.log([]  instanceof  Array); //->true
console.log(/^$/  instanceof  RegExp); //->true
console.log([]  instanceof  Object); //->true
 
console.log([].constructor === Array); //->true
console.log([].constructor === Object); //->false

constructor能夠避免instanceof檢測數組的時候,用Object也是true的問題app

1
console.log({}.constructor === Object); //true<br>console.log([].constructor === Object);//false

 

侷限性:函數

 

1)用instanceof檢測的時候,只要當前的這個類在實例的原型鏈上(能夠經過原型鏈__proto__找到它),檢測出來的結果都是truepost

1
2
3
4
5
var  oDiv = document.getElementById( "div1" );
//HTMLDivElement->HTMLElement->Element->Node->EventTarget->Object
console.log(oDiv  instanceof  HTMLDivElement); //->true
console.log(oDiv  instanceof  Node); //->true
console.log(oDiv  instanceof  Object); //->true  

 

2)基本數據類型的值是不能用instanceof來檢測的性能

1
console.log(1  instanceof  Number); //->false

數組建立的兩種方式(對象、正則、函數...)
對於引用數據類型來講,咱們兩種方式建立出來的都是所屬類的實例,並且都是對象數據類型的值,是沒有區別的this

1
2
var  ary = [];
var  ary =  new  Array;

對於基本數據類型來講,雖然無論哪種方式建立出來的都是所屬類的一個實例(在類的原型上定義的方法均可以使用),可是字面量方式建立出來的是基本數據類型,而實例方式建立出來的是對象數據類型

1
2
3
var  num1 = 1;
var  num2 =  new  Number( "1" );
console.log( typeof  num1, typeof  num2); //->"number" "object"  

 

3)在類的原型繼承中,instanceof檢測出來的結果實際上是不許確的

1
2
3
function  Fn() {}
var  f =  new  Fn;
console.log(f  instanceof  Array); //->false f不是一個數組,它就是一個普通的實例(普通的對象)

雖然Fn繼承了Array,可是f沒有length和數字索引哪些東西,因此f應該不是數組纔對,可是用instanceof檢測的結果倒是true,由於f雖然不是數組,可是在f的原型鏈上能夠找到Array

1
2
3
4
5
function  Fn() {
}
Fn.prototype =  new  Array; //->Fn子類繼承了Array這個父類中的屬性和方法
var  f =  new  Fn;
console.log(f  instanceof  Array); //->true

  

三、Object.prototype.toString.call(value) ->找到Object原型上的toString方法,讓方法執行,而且讓方法中的this變爲value(value->就是咱們要檢測數據類型的值)

Object.prototype.toString經常使用來判斷對象值屬於哪一種內置屬性,它返回一個JSON字符串——"[object 數據類型]"。

因爲許多引用類型都重寫了Object繼承來的的toStrong方法,因此咱們一般使用call或者apply借用Object.prototype.toString函數來判斷數據類型。

固然,這樣調用的默認前提是Object.prototype.toString沒有被重寫。

toString:一個方法,轉換爲字符串數據類型用的方法
每個數據類型所屬類的原型上都有toString方法,例如:Number.prototype/String.prototype/Array.prototype/Function.prototype...
除了Object上的toString,其餘類原型上的toString都是把當前的數據值轉換爲字符串的意思

null和undefined比較的特殊:他們所屬類Null/Undefined的原型上也有toString,只不過不讓咱們用而已,不只如此其實類的原型都給屏蔽了

HTML元素對象的toString:雖然它的原型鏈很長,可是在其它類的原型上都沒有toString,只有在最底層Object.prototype這上纔有

1
2
3
4
5
6
7
var  oDiv = document.getElementById( "div1" );
oDiv.toString();  //->調用的其實也是Object.prototype.toString...
 
//alert、document.write 這兩種輸出的方式其實都是把要輸出的內容先轉換爲字符串,而後再輸出的<br>
alert([]);  //->""
alert( true );  //->"true"
alert({});  //->這個就要調用Object.prototype上的toString了 ->"[object Object]"

 

複製代碼
//定義toString變量是爲了簡便書寫,同時下降做用域鏈檢索的性能損耗
var toString = Object.prototype.toString;
console.log(toString.call(1));//[object Number]
console.log(toString.call(undefined));//[object Undefined]
console.log(toString.call(null));//[object Null]
console.log(toString.call(false));//[object Boolean]
console.log(toString.call("s"));//[object String]
console.log(toString.call({}));//[object Object]
console.log(toString.call(/[a]/g));//[object RegExp]
console.log(toString.call(function(){}));//[object Function]
複製代碼

 

is系列函數的簡易實現

在明白數據類型怎麼檢測後,下面咱們來簡單實現is系列檢測函數。

複製代碼
var dataType = {
        '[object Null]' : 'null',
        '[object Undefined]' : 'undefiend',
        '[object Boolean]' : 'boolean',
        '[object Number]' : 'number',
        '[object String]' : 'string',
        '[object Function]' : 'function',
        '[object Array]' : 'array',
        '[object Date]' : 'date',
        '[object RegExp]' : 'regexp',
        '[object Object]' : 'object',
        '[object Error]' : 'error'
    },
    toString = Object.prototype.toString;

function type(obj) {
    return dataType[toString.call(obj)];
}

//生成is系列函數
function createValidType() {
    for(var p in dataType) {
        var objType = p.slice(8, -1);
        (function(objType) {
            window['is' + objType] = function(obj) {
                return type(obj) === objType.toLowerCase();
            }
        })(objType)
    }
}
createValidType();

console.log(isObject({}));//true
console.log(isDate(new Date()));//true
console.log(isBoolean(false));//true
console.log(isString(1));//false
console.log(isError(1));//false
console.log(isError(new Error()));//true
console.log(isArray([]));//true
console.log(isArray(1));//false
複製代碼

上面代碼裏分別實現了isNull、isUndefined、isBoolean、isNumber、isString、isFunction、isArray、isDate、isRegExp、isObject、isError這11個檢測函數。同時也實現了type函數,用以檢測數據類型。

複製代碼
console.log(type({}));//"object"
console.log(type(new Date()));//"date"
console.log(type(false));//"boolean"
console.log(type(1));//"number"
console.log(type(1));//"number"
console.log(type(new Error()));//"error"
console.log(type([]));//"array"
console.log(type(1));//"number"
複製代碼

createValidType函數巧用閉包保存數據狀態的特性,批量生成is系列函數。

轉載自:http://www.cnblogs.com/allenlei/p/6161022.html

相關文章
相關標籤/搜索