`

转 Javascript中判断数组的正确姿势

 
阅读更多

原文:http://www.cnblogs.com/zichi/p/5103842.html

在 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]';
}
分享到:
评论

相关推荐

    javascript中数组、对象

    在JavaScript中,数组和对象是两种非常基础且重要的数据结构,它们被广泛应用于各种场景,如数据存储、逻辑处理和对象表示。这篇文章将深入探讨这两种数据类型,以及相关的操作和工具。 **一、数组** 数组在...

    js判断数组是否相等的方法

    在JavaScript中,判断两个数组是否相等是一个常见的需求,尤其在处理数据比较或者验证时。根据标题和描述,我们可以区分两种不同的场景: 1. **数组完全相等**:在这种情况下,不仅要求数组中的元素相同,而且元素...

    JavaScript如何删除数组元素!

    在JavaScript中,数组是一种常用的数据结构,用于存储一系列的值。有时我们可能需要根据特定条件或索引从数组中删除元素。本篇文章将详细介绍几种在JavaScript中删除数组元素的方法,帮助开发者更好地理解和应用这些...

    JavaScript中的数组特性介绍.docx

    JavaScript中的数组是一个强大的数据结构,它具有与其他编程语言中数组不同的特性和行为。在这个文档中,我们将深入探讨JavaScript数组的三个关键特性以及四种创建数组的方法。 1. **无类型(Untyped)** ...

    JavaScript 对象与数组参考大全

    以及与其相关的属性方法,以及事件处理程序,还注明了该对象或数组的父对象用户同样可能需要参考Online Companion中的超级文本Object Hierarchy页面(http://www.netscapepress.com/support/javascript/10-9.htm),以便...

    JavaScript如何获取数组最大值和最小值

    在JavaScript中,获取数组的最大值和最小值是常见的操作,特别是在数据分析、数据处理或界面动态更新等场景。这里我们将详细探讨如何使用JavaScript实现这个功能。 首先,我们可以使用内置的Math对象中的`Math.max...

    JavaScript splice 数组操作(删除,插入)

    JavaScript splice 数组操作(删除,插入)JavaScript splice 数组操作(删除,插入)JavaScript splice 数组操作(删除,插入)JavaScript splice 数组操作(删除,插入)JavaScript splice 数组操作(删除,插入)...

    Javascript数组及其操作

    在 Javascript 中,可以使用三种方式创建数组: 1. 单纯创建数组:`var arr = new Array();` 2. 创建数组的同时规定数组大小:`var arr = new Array(10);` 3. 直接初始化数组:`var arr = new Array("love", "hate...

    javascript判断数组内是否重复的方法

    总之,判断JavaScript数组中是否存在重复元素可以通过多种方法实现,如双重循环、哈希表以及创建新数组等。其中,使用哈希表的方法在性能上具有显著优势,尤其适用于处理大量数据。理解并掌握这些技巧,有助于我们在...

    JavaScript对象与数组参考大全

    在JavaScript中,数组具有的特性包括: 1. **创建数组**:使用字面量语法`var arr = [value1, value2, ...]`或构造函数`var arr = new Array()`。 2. **数组长度**:`length`属性返回数组的元素数量。 3. **索引...

    JavaScript判断数组是否存在key的简单实例

    在JavaScript中,数组和对象的界限有时会变得模糊。当涉及到检查数组中是否存在特定的键(key)时,一个常见的误解是使用`ary[key] == undefined`来判断。这种方法并不总是可靠的,因为可能存在这样的情况:`ary = {...

    JavaScript数组用法详解

    数组直接量是一种简洁的创建数组的方式,只需要将元素用逗号分隔,放入方括号中即可。 数组的 length 属性是一个特殊的属性,它自动更新数组的长度。数组的 length 属性总是比数组的最大元素的索引多 1。数组的元素...

    JavaScript 实现合并数组并排序

    JavaScript 实现合并数组并排序

    JavaScript对象与数组参考大全JavaScript语法结构

    在本篇内容中,我们将深入探讨JavaScript对象和数组的详细知识。 一、JavaScript对象 1. 对象定义:JavaScript对象是一种键值对的集合,键通常是字符串,而值可以是任何类型的数据。对象用花括号 `{}` 包裹,键值对...

    JS判断数组里是否有重复元素的方法小结

    总结上述方法,我们可以看到JavaScript中判断数组重复元素有多种技巧,每种方法都有其适用场景和局限性。在实际应用时,可以根据数据类型和数组大小选择合适的方法。对于大规模数据集,第三种方法(数组排序后比较...

    javascript对象与数组参考大全

    根据提供的文件信息,我们可以从标题、描述以及部分内容中提取出关于JavaScript对象与数组的重要知识点。 ### JavaScript对象与数组参考大全 #### 一、JavaScript对象详解 **1. Anchor对象** - **简介**: `...

    JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍_.docx

    JavaScript中的数组遍历forEach()与map()方法以及兼容写法介绍_.docx

    javascript怎么删除数组的指定元素.docx

    在JavaScript中,数组是一种常用的数据结构,用于存储一系列的值。在处理数组时,有时我们需要删除其中的某个或某些特定元素。本篇文章将详细介绍两种在JavaScript中删除数组指定元素的方法:`splice`方法和`delete`...

    javascript中FOREACH数组方法使用示例.docx

    ### JavaScript中的`Array.prototype.forEach()`方法详解 在JavaScript编程中,处理数组是非常常见的需求之一。随着ES5的引入,开发者拥有了更多强大的工具来操作数组,`Array.prototype.forEach()`便是其中之一。...

Global site tag (gtag.js) - Google Analytics