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

相关文章
相关标签/搜索