js isArray小结

原文:[转载]js isArray小结

在日常开发中,我们经常需要判断某个对象是否是数组类型的,在js中检测对象类型的常见的方法有几种:



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

Js代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. alert(typeof null); // "object"

  2. alert(typeof []); // "object"


2、instanceof操作符。此操作符检测对象的原型链是否指向构造函数的prototype对象,恩,听起来不错,应该可以解决我们的数组检测问题:

Js代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. var arr = [];

  2. alert(arr instanceof Array); // true


3、对象的constructor属性。除了instanceof,我们还可以利用每个对象都具有constructor的属性来判断其类型,于是乎我们可以这样做:

Js代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. var arr = [];

  2. alert(arr.constructor == Array); // true


貌似后两个解决方案是无懈可击的,但真的是这样么?天有不测风云,当你在多个frame中来回穿梭的时候,令人沮丧的问题出现了:

Js代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. var iframe = document.createElement_x(‘iframe‘);

  2. document.body.appendChild(iframe);

  3. xArray = window.frames[window.frames.length-1].Array;

  4. var arr = new xArray(1,2,3); // [1,2,3]

  5. // 哎呀!

  6. arr instanceof Array; // false

  7. // 哎呀呀!

  8. arr.constructor === Array; // false


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

Js代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. isArray: function(object) {

  2. return object != null && typeof object == "object" &&

  3. ‘splice‘ in object && ‘join‘ in object;

  4. }


isArray:”object,你有splice、join这两个数组特有的方法吗?”
object:“嗯,没错我有!”

isArray:“好吧,那你就是个数组了,哪怕你是冒充的,囧……”

Js代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. var trickster = { splice: 1, join: 2 };

  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代码  isArray小结" alt="收藏代码"
src="http://www.iteye.com/images/icon_star.png">

  1. function isArray(o) {

  2. return Object.prototype.toString.call(o) === ‘[object Array]‘;

  3. }




call改变toString的this引用为待检测的对象,返回此对象的字符串表示,然后对比此字符串是否是‘[object
Array]‘,以判断其是否是Array的实例。也许你要问了,为什么不直接o.toString()?嗯,虽然Array继承自Object,也会有
toString方法,但是这个方法有可能会被改写而达不到我们的要求,而Object.prototype则是老虎的屁股,很少有人敢去碰它的,所以能
一定程度保证其“纯洁性”:)


与前面几个方案不同,这个方法很好的解决了跨frame对象构建的问题,经过测试,各大浏览器兼容性也很好,可以放心使用。一个好消息是,很多框
架,比如jQuery、Base2等等,都计划借鉴此方法以实现某些特殊的,比如数组、正则表达式等对象的类型判定,不用我们自己写了。

js isArray小结

时间: 2024-10-14 12:20:04

js isArray小结的相关文章

js加强小结

一)回顾JavaScript基础 (1)函数的定义方式 *>>正常方式 function add(num1,num2){...} >>构造器方式 var add = new Function("num1","num2","return num1+num2"); *>>匿名/无名方式 var add = function(num1,num2){函数体} (2)window对象是什么 在JS中,window表示整个

js 事件小结

1,事件对象   e || window.event //ie   2, 取鼠标点击坐标 带有滚动条的   var top = document.documentElement.scrollTop || document.body.scrollTop;//chorme var x = top + e.clientX; //可视区坐标   3, 获取屏幕坐标 e.screenX e.screenY   4, shiftKey altKey ctrlkey   5,onkeydown/onkeyup

JS——函数小结(1)

函数的声明和冒充 要了解call和apply就要从JS的函数开始说明,函数的声明包括三种方式 <span style="font-size:18px;">一般的声明方法 function box(num1,num2){ return num1+num2; } alert(box(1,3));//4 //使用变量初始化函数 var box=function(num1,num2){ return num1+num2; }; alert(box(1,3));//4 //使用Fun

JS系列——Linq to js使用小结

前言:前面几篇介绍了下C#基础技术中的几个:反射.特性.泛型.序列化.扩展方法.Linq to Xml等,本来还有两三个知识点没有写完,比如委托.多线程.异步等,后面会陆续将它们补起来,以便作为一套完整的系列.之所以有这篇是因为目前BS项目中前端经常需要对Json的数组对象进行筛选.查找.判断是否存在等操作.这时就想到了好用的Linq.博主几年前用过Linq to js,那个时候还觉得那样写很别扭,于是没有重视.现在随着前段业务的越来越复杂,对前端的数据处理要求也越来越高,使用一种快捷的集合操作

JS——函数小结(2)

匿名函数和闭包 到目前为止我们学过的函数都有一个函数名通过函数名传递相应的参数调用该函数,但是这次在JS中的接触到函数可以没有名字名字就是匿名函数.那么我们一般是如何调用匿名函数的呢 方法一:这也是函数的一种声明方式 var sum=function(x,y) { return x+y; } alert(sum (2,3)); // "5" 方法二:匿名函数还能够进行自我执行 Alert((function(x,y) { return x+y;})(2,3)); 匿名函数的自我执行可以

JS——DOM小结(二)操作节点

在DOM总结(一)中已经说明节点有三类:元素节点.属性节点.文本节点这三个节点拥有相同的三个属性,而且可以通过元素节点可以获得当前节点的父节点和子节点.同时可以通过DOM对节点进行增.删.改.查.首先来总体的整理一些思路然后一个一个的进行理解. 图中节点的三个属性nodeName.nodeType.nodeValue可以获得节点的名称.类型.值,三种类型的节点中元素节点具有其特殊性,即可以通过当前的元素节点获得该节点的同级节点.子节点.父节点.同级节点. 通过实例看看效果 在HTML中 <bod

关于闭包的理解(JS学习小结)

前言: 啊啊啊,看书真的很痛苦啊,还是好想做项目写代码才有意思,不过我现在缺的确是将知识体系化,所以不论看书多么痛苦都一定要坚持坚持啊,这才是我现在最需要的进步的地方,加油! 因为现在期末啦,下周一也就是明天开始就有考试,所以复习是主要的事情,看书的速度比较慢了,一周大概也就184页(P110-P284), 虽然页数比较少但是其中有ES中非常最重要的两个概念——原型链和闭包,之前对于两个知识的了解算是知其然不知其所以然的,所以在那两章我也有意多花费了时间,确保我能够吃透这个概念.以下算是我自己的

js数组小结

1.js数组使用sort()排序 var a = ["1","12","3","4","0"]; document.write(a.sort(function(a,b){ //实现升序排序 return a - b; })); 2.js使用数组实现一些数据结构 栈        push() , pop() 队列 shift() ,  push() 反向队列    unshift() , pop() 其中

js跨越小结

javascript跨域有几种情况: 1.基于同一父域的子域之间,如:a.c.com和b.c.com 2.基于不同的父域之间,如:www.a.com和www.b.com 3.端口的不同,如:www.a.com:8080和www.a.com:8088 4.协议不同,如:http://www.a.com和https://www.a.com 对于情况3和4,需要通过后台proxy来解决,具体方式如下: a.在发起方的域下创建proxy程序 b.发起方的js调用本域下的proxy程序 c.proxy将请