(迁移自旧博客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 对象。

版权声明:本文为ym7583306原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/ym7583306/p/10390216.html