細說javascript typeof操作符


細說javascript typeof操作符 

typeof定義

    typeof是一元運算符,用來返回操作數類型的字符串。下面是ECAMScript5.1關於typeof的標准定義:

    

    NOTE:上面表格標紅處應為“object”。

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 操作符的運算結果。

    仔細觀察上面的javascript類型表格,聰明的你也許已經發現了問題所在:type列大多數情況下都返回 "object"並且和class列的值不一致。因此可以說typeof運算符可以用來獲取操作數類型,但很可能得不到想要的結果,所以不應該用typeof來檢測對象的類型。說的這里你可能會有疑惑了,typeof不能用來檢測對象類型那用來干嘛,到底該怎么檢測對象的類型?

    別着急,先來看看對象的[[Class]]這個內部屬性:

  

    對於object的內部屬性[[Class]],ECMAScript5.1是這么說的:ECAMScript規范每種內置對象都定義了 [[Class]] 內部屬性。宿主對象的 [[Class]] 內部屬性的值可以是"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String" 的任何字符串。[[Class]] 內部屬性的值用於內部區分對象的種類。

  NOTE:規范中除了通過 Object.prototype.toString ( ) 沒有提供任何手段使程序訪問此值。

  明白了,原來可以通過 Object.prototype 上的toString()方法獲取[[Class]]屬性,[[Class]]屬性就是對象的真正類型,那我們就來看看Object.prototype.toString ( ) 是何方聖神:

    

    是不是有點豁然開朗的感覺,於是很快寫出以下代碼:

/**
 * _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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM