细说javascript typeof操做符

细说javascript typeof操做符 

typeof定义

    typeof是一元运算符,用来返回操做数类型的字符串。下面是ECAMScript5.1关于typeof的标准定义:javascript

    

    NOTE:上面表格标红处应为“object”。java

typeof疑惑

Value               Class      Type
-------------------------------------
null                null       object
"foo"               String     string
new String("foo")   String     object
1.2                 Number     number
new Number(1.2)     Number     object
true                Boolean    boolean
new Boolean(true)   Boolean    object
new Date()          Date       object
new Error()         Error      object
[1,2,3]             Array      object
new Array(1, 2, 3)  Array      object
new Function("")    Function   function
/abc/g              RegExp     object
new RegExp("meow")  RegExp     object
{}                  Object     object
new Object()        Object     object

    NOTE:上面表格中,Class 一列表示对象的内部属性 [[Class]] 的值,Type 一列表示 typeof 操做符的运算结果。jquery

    仔细观察上面的javascript类型表格,聪明的你也许已经发现了问题所在:type列大多数状况下都返回 "object"而且和class列的值不一致。所以能够说typeof运算符能够用来获取操做数类型,但极可能得不到想要的结果,因此不该该用typeof来检测对象的类型。说的这里你可能会有疑惑了,typeof不能用来检测对象类型那用来干吗,到底该怎么检测对象的类型?git

    别着急,先来看看对象的[[Class]]这个内部属性:github

  

    对于object的内部属性[[Class]],ECMAScript5.1是这么说的:ECAMScript规范每种内置对象都定义了 [[Class]] 内部属性。宿主对象的 [[Class]] 内部属性的值能够是"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String" 的任何字符串。[[Class]] 内部属性的值用于内部区分对象的种类。浏览器

  NOTE:规范中除了经过 Object.prototype.toString ( ) 没有提供任何手段使程序访问此值。ecmascript

  明白了,原来能够经过 Object.prototype 上的toString()方法获取[[Class]]属性,[[Class]]属性就是对象的真正类型,那咱们就来看看Object.prototype.toString ( ) 是何方圣神:ide

    

    是否是有点豁然开朗的感受,因而很快写出如下代码:函数

/**
 * _typeof() returns type of obj
 *
 * @obj 要检测的对象
 */
function _typeof(obj) {

    // Object.prototype.toString 返回一种标准格式字符串("[object ", class, and "]"),
    // 因此经过 slice 截取指定位置的字符串
    return Object.prototype.toString.call(obj).slice(8, -1);
}

//测试结果
>_typrof([])
‘Array’

>_typrof(null)
‘null>typrof  new abc/g
‘RegExp’

    到这里你们也许会想不过如此,若是你真的这么认为,只能对你说句Too young Too simple,请往下看:测试

// IE678
Object.prototype.toString.call(null)         // "[object Object]"
Object.prototype.toString.call(undefined)    // "[object Object]"

    那么到底如何正确的判断javascript的数据类型又作到浏览器的兼容呢,聪明的你应该已经想到了jquery,来看看jQuery.type()是怎样实现的:

var class2type = {};

"Boolean Number String Function Array Date RegExp Object Error".split(" ").forEach(function (e, i) {
    class2type["[object " + e + "]"] = e.toLowerCase();
});

//固然为了兼容IE低版本,forEach须要一个polyfill,不做细谈了。
function _typeof(obj) {

    if (obj == null) {
        return String(obj);
    }

    return typeof obj === "object" || typeof obj === "function" ?
    class2type[class2type.toString.call(obj)] || "object" : typeof obj;
}

// IE678
>_typrof(null)
‘null>_typrof(undefined)
‘undefined

    关于数据类型的判断到这里就告一段落了,既然typeof不能用做数据类型的判断,那typeof能够应用在哪方面呢,往下看。

typeof用途

  1.检测变量是否认义或是否赋值     

        Typeof会在两种状况下返回‘undefined’::一个变量没有被声明的时候,和一个变量的值是undefined的时候。

    > typeof undeclaredVariable 

   'undefined'

 

   > var declaredVariable;

   > typeof declaredVariable

       'undefined'

  2.区分对象值和原始值
function isObject(obj) {
    var type = typeof obj;

    //typeof把函数和对象当作是不一样的类型,并且typeof null返回"object"
    return (type === 'function' || (type === 'object' && !!Obj));
}
  3.某个值是不是函数
function isFunction(obj) {

    //这样作是会出现兼容性的问题(IE 11, Safari 8),有兴趣的朋友能够去了解
    return typeof obj === 'function';
}

总结

    经过本文咱们了解到,检测一个对象的类型尽可能使用Object.prototype.toString()方法,以及如何作到个浏览器的兼容性。关于typeof操做符,虽然列举了几个典型的应用场景,不过建议除非为了检测一个变量是否已经定义,尽可能避免使用typeof操做符。

参考

    http://es5.github.io/

    http://lzw.me/pages/ecmascript/

    http://bonsaiden.github.io/JavaScript-Garden/zh/

相关文章
相关标签/搜索