在 Javascript 中,如何判断一个变量是否是数组?

最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的):

var a = [0, 1, 2];
console.log(Array.isArray(a)); // true

但是鉴于低版本 IE 不支持 ES5,如需兼容,需要想想别的办法。

typeof

我们都知道,数组是特殊的对象,所以数组的 typeof 结果也是 object,而因为 null 的结果也是 object,所以如需用 typeof 运算符来判断数组,需要这么写:

var a = [0, 1, 2];
// 是 object 同时排除 null、排除纯对象
console.log(typeof a === 'object' && a !== null && Object.prototype.toString.call(a) !== '[object Object]');  // true

instanceof

来回忆下 instanceof 运算符的使用方式。a instanceof b,如果返回 true,表示 a 是 b 的一个实例。那么如果 a instanceof Array 返回 true,是不是就说明 a 是 数组类型呢?跟 instanceof 师出同门的还有 constructor,是否同样可以判断呢?

var a = [0, 1, 2];
console.log(a instanceof Array);  // true 就是数组?
console.log(a.constructor === Array); // true 数组?

答案是否定的,需要注意嵌套 frame 的情况。

index.htm 代码:

<iframe src='a.htm'></iframe>
<script>
    window.onload = function() {
      var a = window.frames[0].a;
      console.log(a instanceof Array);  // false
      console.log(a.constructor === Array);  // false
    };
</script>

a.htm 代码:

<script>
  window.a = [1, 2, 3];
</script>

我们看到 index.htm 代码中,变量 a 确实是一个数组,但是 a instanceof Array 的结果却是 false。

这是因为每个 frame 都有一套自己的执行环境,跨 frame 实例化的对象彼此不共享原型链。如果打印 a instanceof window.frames[0].Array,那么结果就是 true 了。

特性嗅探?

var a = [0, 1, 2];

if (a.sort) {
  // 是数组
}

也不靠谱,万一某个对象正好有值为 sort 的 key 呢?

var a = {sort: 'me'};

if (a.sort) {
  // 数组?
  // 其实我真的不是数组
}

正确的姿势是使用 Object.prototype.toString() 判断:

var a = [0, 1, 2];
console.log(Object.prototype.toString.call(a) === '[object Array]'); // true

事实上,这也是一些类库进行数组(甚至其他类型)判断的主流方式。

比如在 jQuery 中进行数组判断的相关代码(PS:摘自 jQuery 1.10.1,最近版本的 jQuery 只保留了 Array.isArray(),没有对不支持 ES5 的浏览器做兼容):

isArray: Array.isArray || function( obj ) {
    return jQuery.type(obj) === "array";
},

type: function( obj ) {
    if ( obj == null ) {
        return String( obj );
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ core_toString.call(obj) ] || "object" :
        typeof obj;
},

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

代码很清晰,如支持原生的 Array.isArray(),则直接判断,不支持的话调用 toString() 进行判断。同时可以看到很多其他类型变量的判断也是基于 toString() 方法。当然这里说的 toString() 均是 Object 原型链上的 toString() 方法。

console.log(Object.prototype.toString.call(10));  // [object Number]
console.log(Object.prototype.toString.call('hello')); // [object String]
console.log(Object.prototype.toString.call(true));  // [object Boolean]
console.log(Object.prototype.toString.call([]));  // [object Array]
console.log(Object.prototype.toString.call({}));  // [object Object]
console.log(Object.prototype.toString.call(function(){}));  // [object Function]
console.log(Object.prototype.toString.call(/a/g));  // [object RegExp]
console.log(Object.prototype.toString.call(null));  // [object Null]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(new Date())); // [object Date]

Object.prototype.toString() 为何能返回这样类型的字符串?

ECMA-262:

Object.prototype.toString( ) When the toString method is called, the following steps are taken:
1. Get the [[Class]] property of this object.
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”.
3. Return Result (2) 

上面的规范定义了 Object.prototype.toString 的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于 "[object Array]" 的字符串作为结果([[]]用来表示语言内部用到的、外部不可直接访问的属性,称为 "内部属性")。利用这个方法,再配合 call,我们可以取得任何对象的内部属性 [[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。还是先来看看在 ECMA 标准中 Array 的描述吧:

new Array([ item0[, item1 [,…]]])
The [[Class]] property of the newly constructed object is set to “Array”.

所以 Javascript 中判断数组的函数可以这样写:

function isArray(a) {
  Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]';
}

Read More:

Javascript中判断数组的正确姿势的更多相关文章

  1. javascript中的数组扩展(一)

     javascript中的数组扩展(一) 随着学习的深入,发现需要学习的关于数组的内容也越来越多,后面将会慢慢归纳,有的是对前面的强化,有些则是关于前面的补充. 一.数组的本质    数组是按照次序排 ...

  2. JavaScript中判断为整数的多种方式

    之前记录过JavaScript中判断为数字类型的多种方式,这篇看看如何判断为整数类型(Integer). JavaScript中不区分整数和浮点数,所有数字内部都采用64位浮点格式表示,和Java的d ...

  3. JavaScript中判断整字类型最简洁的实现方法

    这篇文章主要介绍了JavaScript中判断整字类型最简洁的实现方法,本文给出多个判断整数的方法,最后总结出一个最短.最简洁的实现方法,需要的朋友可以参考下 我们知道JavaScript提供了type ...

  4. JavaScript中的数组和字符串

    知识内容: 1.JavaScript中的数组 2.JavaScript中的字符串 一.JavaScript中的数组 1.JavaScript中的数组是什么 数组指的是数据的有序列表,每种语言基本上都有 ...

  5. JavaScript中判断变量类型最简洁的实现方法以及自动类型转换(#################################)

    这篇文章主要介绍了JavaScript中判断整字类型最简洁的实现方法,本文给出多个判断整数的方法,最后总结出一个最短.最简洁的实现方法,需要的朋友可以参考下 我们知道JavaScript提供了type ...

  6. JavaScript中的数组创建

    JavaScript中的数组创建 数组是一个包含了对象或原始类型的有序集合.很难想象一个不使用数组的程序会是什么样. 以下是几种操作数组的方式: 初始化数组并设置初始值 通过索引访问数组元素 添加新元 ...

  7. JavaScript中Array(数组) 对象

    JavaScript中Array 对象 JavaScript中创建数组有两种方式 (一)使用直接量表示法: var arr4 = []; //创建一个空数组var arr5 = [20]; // 创建 ...

  8. 前端开发:Javascript中的数组,常用方法解析

    前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ...

  9. JavaScript中的数组详解

    JavaScript中的数组 一.数组的定义 数组是值的有序集合,或者说数组都是数据的有序列表. 二.创建数组 [字面量形式] 1.空数组 var arr=[]; 2.带有元素的数组 var arr= ...

随机推荐

  1. Mongodb Manual阅读笔记:CH6 聚合

    6 聚合 Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mongodb Manual阅读笔 ...

  2. 初次体验VS2015正式版,安装详细过程。

    本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 阅读目录 介绍 安装 其他 本文版权归mephi ...

  3. SQL Server调优系列进阶篇(查询优化器的运行方式)

    前言 前面我们的几篇文章介绍了一系列关于运算符的基础介绍,以及各个运算符的优化方式和技巧.其中涵盖:查看执行计划的方式.几种数据集常用的连接方式.联合运算符方式.并行运算符等一系列的我们常见的运算符. ...

  4. jqGrid 最常用的属性和事件,供平时参考(转)

    [html] <html> ... <table id="list1"></table> <div id="pager1&quo ...

  5. Spark SQL 之 Migration Guide

    Spark SQL 之 Migration Guide 支持的Hive功能 转载请注明出处:http://www.cnblogs.com/BYRans/ Migration Guide 与Hive的兼 ...

  6. viso2010从mysql中导出ER图

    mysql connector 下载地址: http://dev.mysql.com/downloads/connector/odbc/5.1.html 首先机器要安装mysql-connector- ...

  7. WPF学习笔记(一):数据绑定之元素到元素绑定

    前言 作为一只菜鸟,之前学了一段时间的WPF,但是没有总结,过了一学期发现好多东西都忘记了,很多东西还是需要记下来,以备后续复习. 数据绑定在事件中应用非常广泛,可以有效地减少代码量,那么什么是数据绑 ...

  8. USACO GCD Extreme(II)

    题目大意:求gcd(1,2)+gcd(1,3)+gcd(2,3)+...+gcd(n-1,n) ---------------------------------------------------- ...

  9. 关于log4j的讨论

    1.LoggersLoggers组件在此系统中被分为五个级别:DEBUG.INFO.WARN.ERROR和FATAL.这五个级别是有顺序的,DEBUG < INFO < WARN < ...

  10. 已Access为支持,书写一个C#写入的记录的方案

      /// <summary> /// 读取Excel文档 /// </summary> /// <param name="Path">文件名称 ...