如何判断一个对象是数组

文章目录

  • 一、typeof方法
  • 二、Instanceof与constructor属性
    • 1.Instanceof
    • 2.constructor属性
    • 注意
  • 三、Object.prototype.toString.call()方法
  • 四、Array.isArray()
  • 总结


一、typeof方法

当涉及到检测数据的问题时,我们首先想到的可能就是用typeof来检测数据类型。

其中typeof返回示例如下:

    // 数值
    typeof 23 === 'number';

    // 字符串
    typeof '' === 'string';

    // 布尔值
    typeof false === 'boolean';

    // Symbols
    typeof Symbol() === 'symbol';

    // Undefined
    typeof undefined === 'undefined';

    // 对象
    typeof {
      a: 1 } === 'object';
    typeof [1, 2, 4] === 'object';

    // 函数
    typeof function () {
      } === 'function';
//注意:    
    // 下面的例子令人迷惑,非常危险,没有用处。避免使用它们。
    typeof new Boolean(true) === 'object';
    typeof new Number(1) === 'object';
    typeof new String('abc') === 'object';

由上例我们可以看出,对于Function, String, Number, Undefined等这几种基本类型来说,我们可以采用typeof检测。
但是对于数组或者正则(由一个字符序列形成的搜索模式)来说,typeof检测无法满足,因为两者的返回类型都是对象object,所以我们还需另找方法…


二、Instanceof与constructor属性

1.Instanceof

instanceof可以判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上,所以用来检测某对象是否是数组可能更好不过了,直接通过看返回值true与false直接可以判断是否是数组。

代码如下(示例):

        console.log([] instanceof Array); // true
        console.log({
      a: 1 }instanceof Array); // false

2.constructor属性

同样 由于js中每一个对象都有一个constructor属性,它引用了初始化该对象的构造函数,比如判断未知对象的类型。
代码如下(示例):

          //方法重写
          function isArray(obj) {
     
            return typeof obj == 'object' && obj.constructor == Array
          }
          // 测试de
          console.log(isArray([])); // true
          var a = {
     "a":1};
          console.log(isArray(a));   // false
           
          var b = [1,2,3];
          console.log(isArray(b));       // true
          console.log(isArray(/\d+/g));  // false

如上可以看到,通过调用prototype属性与isArray 方法一般情况下可以判断是否为数组的列子

注意

但是这种一般情况真的可以完全判断吗?答案当然是否定的,当对于跨框架iframe的时候使用页面中的数组时:
代码如下(示例):

           var iframe = document.createElement('iframe');
            document.body.appendChild(iframe);
            xArray = window.frames[window.frames.length-1].Array;    
            var arr = new xArray("1","2","3","4","5");
            //这个写法IE下是不支持的,标准浏览器firefox,chrome下有
             
             
            console.log(arr); // 打印出 ["1", "2", "3", "4", "5"]
            console.log(arr instanceof Array); // false 
            console.log(arr.constructor === Array); // false     

失败的关键在于iframe元素的跨平台的特点,使其有一套自己的执行环境,创建的数组无法共享其prototype属性,由于无法共享原型链,所以无法采用如上两种方式判断。


三、Object.prototype.toString.call()方法

以上三种方法都无法准确判断对象是否为数组,有没有比较准确的方法呢,答案当然是肯定的。

        function isArray(obj) {
     
      return Object.prototype.toString.call(obj) == '[object Array]';          //call是用来改变指向的
    }      //方法重写
// 代码调用
          //一般情况
    console.log(isArray([])); // true
    console.log(isArray([1,2,3])); // true
     
         //判断特殊情况,跨平台框架
    var iframe = document.createElement('iframe');
    document.body.appendChild(iframe);
    xArray = window.frames[window.frames.length-1].Array;    
    var arr = new xArray("1","2","3","4","5");
     
    console.log(arr);       // ["1","2","3","4","5"]
    console.log(isArray(arr)); // true       ~   

这时候,可能又有人要说了,这种原型链的方法这么麻烦,有简单一点的吗,当然ECMA-262为我们引入了Array.isArray()方法。


四、Array.isArray()

isArray方法用来准确判断一个值是否为数组,对于IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都可以完美兼容,但是对于IE8之前的版本是不支持的。
但是个人感觉用法来说是最为简便的:

          Array.isArray([])   // true    

总结

对于判断一个对象是数组的问题上,最好的方式如下:

       var arr = [1,2,3];
       var arr2 = [{
      name : 'jack', age : 22 }];
       function isArrayFn(value){
     
    // 判断Array.isArray的兼容性
    if (typeof Array.isArray === "function") {
     
        return Array.isArray(value);
    }else{
     
        return Object.prototype.toString.call(value) === "[object Array]";
        // return obj.__proto__ === Array.prototype;
    }
}
console.log(isArrayFn(arr));  // true
console.log(isArrayFn(arr2));  // true       

补充:原生链的方法不仅看起来较为麻烦,而且执行效率也几乎慢了Array.isArray()一倍,所以我们为了提高代码的执行效率,所以我们可以最先判断Array.isArray()的兼容性问题,之后再考虑选取原型链的方法。

你可能感兴趣的:(js经典问题,javascript)