1. 程式人生 > >Javascript 中的數據類型判斷

Javascript 中的數據類型判斷

script iframe 特性 isnan 性問題 console 應付 執行環境 zhang

(遷移自舊博客2017 09 25)

typeof


我們常使用typeof來判斷數據類型,在常規場景中足以應付數據類型判斷的需要:

    var obj = {
    name: 'zhangxiang'
    };
    function foo() {
        console.log('this is a function');
    }
    var arr = [1,2,3];
    console.log(typeof 1);  // number
    console.log(typeof '1');  //string
    console.log(typeof true);  //boolean
    console.log(typeof null); //object
    console.log(typeof undefined); //undefined
    console.log(typeof obj); //object
    console.log(typeof foo);  //function
    console.log(typeof arr);   //object

typeof可以判斷所有js中的基本數據類型(Null,Undefined,Boolean,String,Number),雖然null使用typeof返回的是object,但是不影響它的基本使用。但是如果想要判斷array,null等,它就起不到作用了。

instanceof


instanceof運算符用來測試一個對象在其原型鏈中是否存在一個構造函數的prototype屬性。
語法:object instanceof constructor
其實它適合於判斷自定義的類實例對象,而不是用來判斷原生的數據類型。

    // a.html
    <script>
      var a = [1,2,3];
    </script>
    //main.html
    <iframe src="a.html"></iframe>
    <script>
      var frame = window.frame[0];
      var a = frame.a;
      console.log(a instanceof Array);  // false
      console.log(a.contructor === Array);  //false
      console.log(a instanceof frame.Array); // true
    </script>

iframe 之間不會共享原型鏈, 因為他們有獨立的執行環境, 所以 frame a 中的數組 a 不會是本執行環境的實例對象。 通過特性嗅探同樣不靠譜, 像通過 contructor,sort, slice 等等的特有的數組(或者其他數據類型)方法或屬性, 萬一對象中也有 sort, slice 屬性, 就會發生誤判。所以最靠譜的方法是使用 Object.prototype.toString 方法。

Object.prototype.toString


使用Object.prototype.toString方法,可以獲取到變量的準確類型。

    function foo(){};
    Object.prototype.toString.call(1);  '[object Number]'
    Object.prototype.toString.call('1'); '[object String]'
    Object.prototype.toString.call(NaN); '[object Number]'
    Object.prototype.toString.call(foo);  '[object Function]'
    Object.prototype.toString.call([1,2,3]); '[object Array]'
    Object.prototype.toString.call(undefined); '[object Undefined]'
    Object.prototype.toString.call(null); '[object Null]'
    Object.prototype.toString.call(true); '[object Boolean]'

Object.prototype.toString 的原理是當調用的時候, 就取值內部的 [[Class]] 屬性值, 然後拼接成 ‘[object ‘ + [[Class]] + ‘]‘ 這樣的字符串並返回. 然後我們使用 call 方法來獲取任何值的數據類型。

有用的數據類型判斷函數


isArray polyfill


isArray 是數組類型內置的數據類型判斷函數, 但是會有兼容性問題, 所以模擬 underscore 中的寫法如下:

isArray = Array.isArray || function(array){
  return Object.prototype.toString.call(array) === '[object Array]';
}

isNaN polyfill

判斷一個數是不是 NaN 不能單純地使用 === 這樣來判斷, 因為 NaN 不與任何數相等, 包括自身, 所以:

isNaN: function(value){
  return isNumber(value) && isNaN(value);
}

這裏的 isNumber 就是用上面所說的Object.prototype.toString進行判斷的,然後使用isNaN來判斷值,至於為什麽需要在判斷 isNaN 之前需要判斷是不是 Number類型,這是因為NaN本身也是數字類型(Object.prototype.toString 可知), 在ES6的isNaN 中只有值為數字類型使用NaN才會返回 true, 這是為了模擬 ES6 的 isNaN。

判斷是否是 DOM 元素


在實際項目裏面, 有時或許我們需要判斷是否是 DOM 元素對象, 那麽在判斷的時候利用的是 DOM 對象特有的 nodeType 屬性:
兼容做法原理是通過對象的 hasOwnProperty 方法來判斷對象是否擁有 callee 屬性從而判斷是不是 arguments 對象.
isElement: function(obj){
return !!(obj && obj.nodeType === 1);
}

判斷是否是對象

isObject: function(obj){
  var type = typeof obj;
  return type === 'function' || typeof === 'object' && obj !== null;
}

這裏的對象是狹義的, 是通常所指的 key-value 型的集合, 或者是 function 函數並且不為 null。

判斷是否是 arguments 對象 polyfill


判斷一個對象是不是 arguments 對象可以通過 Object.prototype.toString 來判斷, 但是低版本的瀏覽器不支持, 他們返回的是 [object Object], 所以需要兼容:

isArguments: function(obj){
  return Object.prototype.toString.call(obj) === '[object Arguments]' || (obj != null && Object.hasOwnProperty.call(obj, 'callee'));
}

兼容做法原理是通過對象的 hasOwnProperty 方法來判斷對象是否擁有 callee 屬性從而判斷是不是 arguments 對象。

Javascript 中的數據類型判斷