很多时候我们需要对JavaScript中数据类型( Function 、 String 、 Number 、 Undefined 、 Boolean 和 Object )做判断。在JavaScript中提供了typeof操作符可以对这些常用的数据类型做判断。但要使用typeof来判断数据是不是一个数组,就不起作用了。那在实际生产中要如何来检测数据是不是一个数组呢?

今天的学习任务就是如何来检测一个数据是不是数组?

typeof操作符

typeof 可以解决大部分数据类型的检测,如:

1 console.log(typeof function () {return;}); //function
2 console.log(typeof "a"); //string
3 console.log(typeof 123); //number
4 console.log(typeof a); //undefined
5 console.log(typeof true); //boolean
6 console.log(typeof NaN); //number
7 console.log(typeof !NaN); //boolean
8 console.log(typeof {name:"大漠",age: "37"}); //object
9 console.log(typeof ["大漠","37"]); //object
10 console.log(typeof null); //object

上面的代码示例告诉我们,typeof {name:"大漠",age: "37"}typeof ["大漠","37"]返回的都是object。事实再次证明typeof没办法对数组进行检测,那么这里引出一个问题?如何判断数据是个数组类型?

检测数组方法

虽然typeof操作符无法检测数组,但事实上检测数组方法有很多种。@Tom、@John、@Rick、@Ken和@Eric在Quora的一篇文章中总结了五种不同的检测数组的方法。接下来我们一起来了解和学习这几种检测数组的方法。

ECMAScript 5的isArray函数

1 functionisArray(obj) {2     returnArray.isArray(obj);3 }4 var arr = ["大漠","w3cplus"]; //创建一个数组
5 isArray(arr); //true

毫无疑问,这看起来最完美的解决方案,因为他是原生的。ECMAScript 5将Array.isArray()引入JavaScript。但其兼容性令你会感到些许的失望:IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都实现了这个方法,但是在IE8之前的版本是不支持的。

在这个基础上对构造函数做一下检测,而且这个检测过程非常的快,而且也非常的准确。事实上对我们的使用太准确了。但在工作是不能确定一个变量是继承自一个数组。这样一来,在某种程度上对构造函数做检测对于我们自己来说是很需要的,也是非常有益的:

1 functionisArray(obj) {2     return (typeof obj !== 'undefined' && obj && obj.constructor ===Array);3 }

对象自身的constructor属性

上面的示例中,检测构造函数时使用了对像自身的constructor属性。其实constructor属性返回一个指向创建了该对象原型的函数引用。使用该属性也可以检测数组类型。

1 var arr = ["大漠","W3cplus"];2 console.log(arr.constructor === Array); //true

instanceof操作符

除了使用对像自身的 constructor 属性检测一个数组之外,还可以使用 instanceof 操作符来检测一个数组。

instanceof 操作符可以用来判断某个构造函数的  prototype  属性是否存在另外一个要检测对象的原型链上。也就是判断instanceof前面的对象是否是后面的类或对象的实例。

注:这个操作符和JavaScript中面向对象有点关系,了解这个就先得了解JavaScript中的面向对象。

来回忆下 instanceof 运算符的使用方式。a instanceof b,如果返回 true,表示 a 是 b 的一个实例。那么如果 a instanceof Array 返回 true,是不是就说明 a 是 数组类型呢?

1 var arr = ["大漠","W3cplus"];2 console.log(arr instanceof Array); //true

frame实例化对象带来的问题

constructor 和 instanceof 貌似很好的两个检测数组的方法,但实际上还是有些漏洞的,当你在多个frame中回来跳的时候,这两种方法就惨了。由于每一个frame都有自己的一套执行环境,跨frame实例化的对象彼此并不共享原型链,通过instanceof操作符和constructor属性检测的方法自然会失败。

1 //创建iframe并添加到DOM中
2 var iframe = document.createElement('iframe'); //创建iframe
3 document.body.appendChild(iframe); //将创建的iframe添加到body中
4 otherArray = window.frames[window.frames.length - 1].Array;5 var arr = new otherArray("大漠","W3cplus"); //声明数组["大漠","W3cplus"]
6 console.log(arr instanceof Array);        //false
7 console.log(arr.constructor === Array);   //false

对象原生toString检测

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

1 isArray = function(obj) {2     return Object.prototype.toString.call(obj) == "[object Array]";3 }4 var arr = ["大漠","W3cplus"];5 console.log(isArray(arr)); //true

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

JavaScript 标准文档中定义: [[Class]] 的值只可能是下面字符串中的一个:ArgumentsArrayBooleanDate,ErrorFunctionJSONMathNumberObjectRegExpString

其它方法

除了上面介绍的一些检测数组的方法之外,还有:

@Rick Waldron提供的:

1 var arr = [1,2,3];2 functionisArray( arg ) {3   if ( typeof arg === "object" &&
4      ( "join" in arg && typeof arg.join === "function" ) &&
5      ( "length" in arg && typeof arg.length === "number") ) {6         return true;7 }8   return false;9 }10 console.log(true, isArray(arr)); //true true
11 console.log(false, isArray({join: true}) ); //false false
12 console.log(false, isArray({join: function () {return false;}}) ); //false false

@Shamasis Bhattacharya 提供的:

1 var isArray = function(subj) {2     try{3         subj && (subj.length = -1);4         return false;5 }6     catch(er) {7         return true;8 }9 };10 var arr = [1,2,3];11 isArray(arr); //true

道格拉斯提供的:

1 var is_array = function(value) {2     return value &&
3         typeof value === 'object' &&
4         typeof value.length === 'number' &&
5         typeof value.splice === 'function' &&
6         !(value.propertyIsEnumerable('length'));7 };8 var arr = [1,2,3];9 is_array(arr); //true

最佳检测方法

其实也没有什么是最佳检测方法,只有最合适的检测方法。综合上面各种检测数组的方法,稍做一些处理:

1 var isArray = (function() {2     if(Array.isArray) {3         returnArray.isArray;4 }5     var objectToStringFn =Object.prototype.toString,6         arrayToStringResult =objectToStringFn.call([]);7
8     return function(subject) {9         return objectToStringFn.call(subject) ===arrayToStringResult;10 };11 }());12
13 var arr =[];14 isArray(arr); //true

最优化的方法就是不管Array.isArray'是否能用,都可以回到对象原生toString检测和对象原生toString`检测上。

转载于:https://www.cnblogs.com/joyco773/p/6274579.html

JavaScript学习笔记:检测数组方法相关推荐

  1. JavaScript学习笔记之 数组方法一 堆栈 和队列

    数组的方法 以及 堆栈的操作的方法 JavaScript是一种弱类型语言,不像其它程序语言需要严格定义数据类型.在JavaScript中数组可以任意修改变动,这样也就出现了一个问题,如果边遍历数组边操 ...

  2. JavaScript学习笔记之数组(二)

    JavaScript学习笔记之数组(二) 1.['1','2','3'].map(parseInt) 输出什么,为什么? ['1','2','3'].map(parseInt)//[1,NaN,NaN ...

  3. JavaScript学习笔记:数组reduce()和reduceRight()方法

    很多时候需要累加数组项的得到一个值(比如说求和).如果你碰到一个类似的问题,你想到的方法是什么呢?会不会和我一样,想到的就是使用for或while循环,对数组进行迭代,依次将他们的值加起来.比如: v ...

  4. JavaScript学习笔记:数组

    文章目录 一.一维数组 1.创建数组 (1)创建空数组,逐个赋值 (2)创建数组同时赋值 (3)创建字面量数组 2.添加数组元素 3.数组长度属性length 4.遍历数组 (1)传统for循环 (2 ...

  5. JavaScript学习笔记(六)--数组

    数组初始化 我们都知道,数组是用于保存多个值的集合,在数组中,值被称为元素,值可以是任意的数据类型.在Javascript中,创建数组通常有两种方式:字面量和构造函数. 字面量 数组的元素可以是任意的 ...

  6. JavaScript学习笔记:类型检测

    JavaScript学习笔记:类型检测 1.利用typeof检测数据类型 注意:type of null,返回的不是"null",而是"object".type ...

  7. 正则至少一个数字_好程序员web前端培训分享JavaScript学习笔记之正则

    好程序员web前端培训分享JavaScript学习笔记之正则,正则表达式,又名 "规则表达式" 由我们自己来书写 "规则",专门用来检测 字符串 是否符合 &q ...

  8. JavaScript 学习笔记(二)

    JavaScript 学习笔记(二) 文章目录 JavaScript 学习笔记(二) 一 JSON 1. JSON 对象 什么是JSON对象 JSON对象与Javascript对象的区别 在JavaS ...

  9. JavaScript学习笔记(一)-Learning Advanced JavaScript

    JavaScript学习笔记 (一)- Learning Advanced JavaScript Learning Advanced JavaScript #2: Goal: To be able t ...

最新文章

  1. 解决webApiMessageAn error has occurred./Message不能写多个Get方法的问题
  2. vSphere可用性之三准备实验环境
  3. 去中心化钱包CoinU基本介绍,你想知道的都有。
  4. DataGridView 的 CurrentCellDirtyStateChanged事件用法
  5. 数学建模 TSP(旅行商问题) Lingo求解
  6. python绘制图像的参数_图像绘制.draw.line():系统错误:新样式getargs格式,但参数不是tup...
  7. Vue入门 ---- vue-loader 、vue-cli
  8. java作业 大蛇丸的召唤术 万蛇罗之阵 类与对象的演练
  9. css盒模型只能应用于html,iframe,css样式表,盒模型的使用方法-2019年9月3日
  10. 关于SQL SERVER 2000在Windows Server 2003下不能使用的问题
  11. jar包 java_深入理解JAR包
  12. java缓冲流和普通流的区别_关于java:数据输入/输出流和缓冲的输入/输出流有什么区别?...
  13. MatLab 2016b下载资源
  14. 当前计算机技术在制图,计算机技术在《机械制图》课程中的应用
  15. 英语各类词担任的句子成分
  16. halcon代码LAWS纹理滤波
  17. android ems具体意义?
  18. ETHEOS开发资源及工具集合
  19. HR SaaS系统,虎蔓开创云端人力资源管理的领先新模式!
  20. demoireing

热门文章

  1. BS-XX-020基于SSM实现停车位租赁系统
  2. Spark快速上手-WordCount案例
  3. Reduce Join介绍及案例
  4. 8月份Github上最热门的Python开源项目
  5. Java-JSON 解析
  6. Linked list(单链表)
  7. Overlapping Rectangles 离散+线段树 +扫描线
  8. C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例
  9. 微信公众平台开发 微信JSSDK开发
  10. H5学习系列之Communication API