Javascript中判断数组的正确姿势

boyanx4周前技术教程5

51RGB

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

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

var a = [0, 1, 2];

console.log(Array.isArray(a)); // true

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

typeof?

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

var a = [0, 1, 2];

// 是 object 同时排除 、排除纯对象

console.log(typeof a === 'object' & a !== && 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 代码:

window.onload = function {

var a = window.frames[0].a;

console.log(a instanceof Array); // false

console.log(a.constructor === Array); // false

};

a.htm 代码:

window.a = [1, 2, 3];

我们看到 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 == ) {

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); // [object ]

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数组类型检测:编写更强壮的isArray函数


  • JavaScript:Object.prototype.toString方法的原理

作者:韩子迟

网址:
http://www.cnblogs.com/zichi/p/5103842.html

想认识志同道合的朋友一起学习web

加入我们的学习QQ群 190166743

丰富的学习资源,周一到周四免费直播公开课

每天直播公开课在线视频和下载

你可能感兴趣的精彩内容

微信:UI设计自学平台加关注

长按关注:《UI设计自学平台》

↓↓↓

标签: js在线测试

相关文章

在Node应用中实施Web认证的四大方法

本文翻译自RisingStack网站Gergely Nemeth撰写的《Web Authentication Methods Explained》一文,感谢景庄对该文章的翻译。安全问题正成为Web应用...

推荐一个检测 JS 内存泄漏的神器

大家好,我是 Echa哥。作为一名 Web 应用程序开发者,排查和修复 JavaScript 代码的内存泄漏一直是最困扰我的问题之一。最近,Meta 开源了一款检测 JavaScript 代码内存泄漏...

Web 服务器基准测试:Go vs. Node.js vs. Nim vs. Bun

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。文章大部分内容...

Linux下使用Speedtest测试网速

Speedtest是用来测试网络性能的开源软件,在Linux下面安装Speedtest可以用来测试网络出口的上传和下载速度,帮助排查网络方面导致的故障。Speedtest介绍由于公司几个项目用户访问的...

你必须知道的 7 个杀手级 JavaScript 单行代码

1.如果你需要一个临时的唯一 ID,请生成随机字符串。这个例子将为你生成一个随机字符串:const randomString = Math.random().toString(36).slice(2)...

程序员的 JavaScript 代码该如何让计算机搞懂?

出自程序员之手的 JavaScript 代码,该如何变成计算机所能理解的机器语言呢?本文将带你走进 JavaScript 引擎内部,一探究竟。作者 | Lydia Hallie译者 | 弯月,责编 |...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。