Javascript isArray 数组类型检测函数


Posted in Javascript onOctober 08, 2009

1、typeof操作符。对于Function、String、Number、Undefined这几种类型的对象来说,不会有什么问题,但是针对Array的对象就没什么用途了:
Js代码

alert(typeof null); // "object" 
alert(typeof []); // "object"

2、instanceof操作符。此操作符检测对象的原型链是否指向构造函数的prototype对象,恩,听起来不错,应该可以解决我们的数组检测问题:
Js代码
var arr = []; 
alert(arr instanceof Array); // true

3、对象的constructor属性。除了instanceof,我们还可以利用每个对象都具有constructor的属性来判断其类型,于是乎我们可以这样做:
Js代码
var arr = []; 
alert(arr.constructor == Array); // true

貌似后两个解决方案是无懈可击的,但真的是这样么?天有不测风云,当你在多个frame中来回穿梭的时候,令人沮丧的问题出现了:
Js代码
var iframe = document.createElement('iframe'); 
document.body.appendChild(iframe); 
xArray = window.frames[window.frames.length-1].Array; 
var arr = new xArray(1,2,3); // [1,2,3] 
// 哎呀! 
arr instanceof Array; // false 
// 哎呀呀! 
arr.constructor === Array; // false

由于每个iframe都有一套自己的执行环境,跨frame实例化的对象彼此是不共享原型链的,因此导致上述检测代码失效!怎么办怎么办??嗯,javascript是动态语言,或许万金油“鸭式辨型”(duck type)可以助我们一臂之力“如果它走起路来像鸭子,叫起来也像鸭子,那就当他是鸭子吧”,同理,可以检测某些数组对象特有的能力来做判断,这个法子已经有人用了,比如Prototype框架,来看看它实现的Object.isArray方法:
Js代码
isArray: function(object) { 
return object != null && typeof object == "object" && 
'splice' in object && 'join' in object; 
}

isArray:”object,你有splice、join这两个数组特有的方法吗?”
object:“嗯,没错我有!”
isArray:“好吧,那你就是个数组了,哪怕你是冒充的,?濉??
Js代码
var trickster = { splice: 1, join: 2 }; 
Object.isArray(trickster); // 假冒成功,耶

没错,这个解决方案给人的感觉有点别扭,任何一个具有'splice'和'join'属性的对象都能通过这个检测!怎么办怎么办怎么办??别着急,仔细想想,其实我们需要的是一个能取得对象实际类型,而且又能跨frame使用的方法即可。这不,细心的老外在翻阅ECMA262标准的时候发现了这个(btw,我也看了,怎么就没发现这个用途呢,?澹?
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]"的字符串作为结果(看过ECMA标准的应该都知道,[[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)。利用这个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。还是先来看看在ECMA标准中Array的描述吧:
ECMA-262 写道
new Array([ item0[, item1 [,…]]]) 
The [[Class]] property of the newly constructed object is set to “Array”.

于是乎,可以改写之前的isArray函数以利用这个特性,如下:
Js代码
function isArray(o) { 
return Object.prototype.toString.call(o) === '[object Array]'; 
}

call改变toString的this引用为待检测的对象,返回此对象的字符串表示,然后对比此字符串是否是'[object Array]',以判断其是否是Array的实例。也许你要问了,为什么不直接o.toString()?嗯,虽然Array继承自Object,也会有toString方法,但是这个方法有可能会被改写而达不到我们的要求,而Object.prototype则是老虎的屁股,很少有人敢去碰它的,所以能一定程度保证其“纯洁性”:)
与前面几个方案不同,这个方法很好的解决了跨frame对象构建的问题,经过测试,各大浏览器兼容性也很好,可以放心使用。一个好消息是,很多框架,比如jQuery、Base2等等,都计划借鉴此方法以实现某些特殊的,比如数组、正则表达式等对象的类型判定,不用我们自己写了。
Javascript 相关文章推荐
JS网页在线获取鼠标坐标值的方法
Feb 28 Javascript
vue中用H5实现文件上传的方法实例代码
May 27 Javascript
微信小程序 空白页重定向解决办法
Jun 27 Javascript
React利用插件和不用插件实现双向绑定的方法详解
Jul 03 Javascript
react-native-video实现视频全屏播放的方法
Mar 19 Javascript
jquery的 filter()方法使用教程
Mar 22 jQuery
基于jQuery实现的设置文本区域的光标位置
Jun 15 jQuery
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
Aug 28 jQuery
jQuery实现数字自动增加或者减少的动画效果示例
Dec 11 jQuery
JS遍历JSON数组及获取JSON数组长度操作示例【测试可用】
Dec 12 Javascript
浅谈在Vue.js中如何实现时间转换指令
Jan 06 Javascript
vuex存取值和映射函数使用说明
Jul 24 Javascript
JavaScript 监听textarea中按键事件
Oct 08 #Javascript
jquery 最简单的属性菜单
Oct 08 #Javascript
Javascript 日期处理之时区问题
Oct 08 #Javascript
学习ExtJS table布局
Oct 08 #Javascript
学习ExtJS accordion布局
Oct 08 #Javascript
学习ExtJS form布局
Oct 08 #Javascript
学习ExtJS fit布局使用说明
Oct 08 #Javascript
You might like
php array_push()数组函数:将一个或多个单元压入数组的末尾(入栈)
2011/07/12 PHP
写一段简单的PHP建立文件夹代码
2015/01/06 PHP
php数组索引与键值操作技巧实例分析
2015/06/24 PHP
Prototype使用指南之dom.js
2007/01/10 Javascript
Node.js中的事件驱动编程详解
2014/08/16 Javascript
jquery实现点击向下展开菜单项(伸缩导航)效果
2015/08/22 Javascript
实例详解jQuery的无new构建
2016/08/02 Javascript
Ajax的概述与实现过程
2016/11/18 Javascript
JS实现登录页密码的显示和隐藏功能
2017/12/06 Javascript
仿京东快报向上滚动的实例
2017/12/13 Javascript
vuejs router history 配置到iis的方法
2018/09/20 Javascript
微信小程序实现左滑修改、删除功能
2020/10/19 Javascript
详解puppeteer使用代理
2018/12/27 Javascript
JavaScript面试技巧之数组的一些不low操作
2019/03/22 Javascript
JavaScript 处理树数据结构的方法示例
2019/06/16 Javascript
JQuery+Bootstrap 自定义全屏Loading插件的示例demo
2019/07/03 jQuery
angular8和ngrx8结合使用的步骤介绍
2019/12/01 Javascript
Python中用Spark模块的使用教程
2015/04/13 Python
Python求两个文本文件以行为单位的交集、并集与差集的方法
2015/06/17 Python
Python的Django中将文件上传至七牛云存储的代码分享
2016/06/03 Python
Python中偏函数用法示例
2018/06/07 Python
Python动态赋值的陷阱知识点总结
2019/03/17 Python
pyqt5利用pyqtDesigner实现登录界面
2019/03/28 Python
pyinstaller打包opencv和numpy程序运行错误解决
2019/08/16 Python
Python之指数与E记法的区别详解
2019/11/21 Python
Python GUI库PyQt5样式QSS子控件介绍
2020/02/25 Python
OpenCV4.1.0+VS2017环境配置的方法步骤
2020/07/09 Python
英国高档百货连锁店:John Lewis
2017/11/20 全球购物
eBay澳大利亚站:eBay.com.au
2018/02/02 全球购物
世界上最大的冷却器制造商:Igloo Coolers
2019/07/23 全球购物
军训心得体会
2013/12/31 职场文书
医疗专业毕业生求职信
2014/08/28 职场文书
2014年体育部工作总结
2014/11/13 职场文书
追讨欠款律师函
2015/05/27 职场文书
浅谈redis整数集为什么不能降级
2021/07/25 Redis
MySQL 执行数据库更新update操作的时候数据库卡死了
2022/05/02 MySQL