JS中如何判断对象是对象还是数组

一、总结

一句话总结:typeof Array.isArray === "function",Array.isArray(value)和Object.prototype.toString.call(value) === "[object Array]"相结合

typeof Array.isArray === "function" 加 Array.isArray(value)
Object.prototype.toString.call(value) === "[object Array]"

综合上面的几种方法,有一个当前的判断数组的最佳写法:

var arr = [1,2,3,1];
var arr2 = [{ abac : 1, abc : 2 }];
function isArrayFn(value){
  if (typeof Array.isArray === "function") {
    return Array.isArray(value);
  }else{
    return Object.prototype.toString.call(value) === "[object Array]";
  }
}
alert(isArrayFn(arr));// true
alert(isArrayFn(arr2));// true

1、【instanceof操作符】象的constructor属性】 在什么情况下判断数组会失败,为什么?

当你在多个frame中来回穿梭的时候
跨frame实例化的对象彼此是不共享原型链的,因此导致上述检测代码失效

instanceof操作符象的constructor属性方法貌似无懈可击,但是实际上还是有些漏洞的,当你在多个frame中来回穿梭的时候,这两种方法就亚历山大了。由于每个iframe都有一套自己的执行环境,跨frame实例化的对象彼此是不共享原型链的,因此导致上述检测代码失效

|||-begin

var iframe = document.createElement('iframe'); //创建iframe
document.body.appendChild(iframe); //添加到body中
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // 声明数组[1,2,3]
alert(arr instanceof Array); // false
alert(arr.constructor === Array); // false

|||-end

2、Object.prototype.toString 的原理和行为是什么 ?

原理是:获取任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较
首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于"[object Array]"的字符串作为结果

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

function isArrayFn (o) {
  return Object.prototype.toString.call(o) === '[object Array]';
}
var arr = [1,2,3,1];
alert(isArrayFn(arr));// true

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

JavaScript
标准文档中定义: [[Class]] 的值只可能是下面字符串中的一个: Arguments, Array, Boolean, Date,
Error, Function, JSON, Math, Number, Object, RegExp, String. 
这种方法在识别内置对象时往往十分有用,但对于自定义对象请不要使用这种方法。

3、用Array.isArray()检测为一个数组是否合理

比较合理,ECMAScript5将Array.isArray()正式引入JavaScript,目的就是准确地检测一个值是否为数组。IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都实现了这个方法。

ECMAScript5将Array.isArray()正式引入JavaScript,目的就是准确地检测一个值是否为数组。IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都实现了这个方法。但是在IE8之前的版本是不支持的。

二、JS中判断对象是对象还是数组的方法

参考:JS中判断对象是对象还是数组的方法
https://www.cnblogs.com/ma-shuai/p/7805264.html">JS中判断对象是对象还是数组的方法

 

JavaScript中检测对象的方法 
1.typeof操作符 
这种方法对于一些常用的类型来说那算是毫无压力,比如Function、String、Number、Undefined等,但是要是检测Array的对象就不起作用了。 利用typeof除了array和null判断为object外,其他的都可以正常判断

alert(typeof null); // "object"
alert(typeof function () {
return 1;
}); // "function"
alert(typeof '梦龙小站'); // "string"
alert(typeof 1); // "number"
alert(typeof a); // "undefined"
alert(typeof undefined); // "undefined"
alert(typeof []); // "object"

2.instanceof操作符 
这个操作符和JavaScript中面向对象有点关系,了解这个就先得了解JavaScript中的面向对象。因为这个操作符是检测对象的原型链是否指向构造函数的prototype对象的。

var arr = [1,2,3,1];
alert(arr instanceof Array); // true

3.对象的constructor属性 
除了instanceof,每个对象还有constructor的属性,利用它似乎也能进行Array的判断。

var arr = [1,2,3,1];
alert(arr.constructor === Array); // true

第2种和第3种方法貌似无懈可击,但是实际上还是有些漏洞的,当你在多个frame中来回穿梭的时候,这两种方法就亚历山大了。由于每个iframe都有一套自己的执行环境,跨frame实例化的对象彼此是不共享原型链的,因此导致上述检测代码失效

var iframe = document.createElement('iframe'); //创建iframe
document.body.appendChild(iframe); //添加到body中
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // 声明数组[1,2,3]
alert(arr instanceof Array); // false
alert(arr.constructor === Array); // false

检测数组类型方法 
以上那些方法看上去无懈可击,但是终究会有些问题,接下来向大家提供一些比较不错的方法,可以说是无懈可击了。 
1.Object.prototype.toString 
Object.prototype.toString的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于"[object Array]"的字符串作为结果(看过ECMA标准的应该都知道,[[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)。利用这 个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。

function isArrayFn (o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
var arr = [1,2,3,1];
alert(isArrayFn(arr));// true

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

JavaScript 标准文档中定义: [[Class]] 的值只可能是下面字符串中的一个: Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String. 
这种方法在识别内置对象时往往十分有用,但对于自定义对象请不要使用这种方法。 
2.Array.isArray() 
ECMAScript5将Array.isArray()正式引入JavaScript,目的就是准确地检测一个值是否为数组。IE9+、 Firefox 4+、Safari 5+、Opera 10.5+和Chrome都实现了这个方法。但是在IE8之前的版本是不支持的。 
3.较好参考 
综合上面的几种方法,有一个当前的判断数组的最佳写法:

var arr = [1,2,3,1];
var arr2 = [{ abac : 1, abc : 2 }];
function isArrayFn(value){
if (typeof Array.isArray === "function") {
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === "[object Array]";
}
}
alert(isArrayFn(arr));// true
alert(isArrayFn(arr2));// true
 

最新文章

  1. ASP.NET Mvc实用框架(一)Ioc、仓储模式和单元工作模式
  2. ora-14400插入的分区关键字未映射到任何分区---oracle数据库表过期问题
  3. 回顾bidirectional path tracing
  4. 使用jquery的小记
  5. makefile 中定义宏位置需要注意一下
  6. 插入排序 --- 排序算法 --- 算法 --- java
  7. 项目源码--Android美图秀秀源码
  8. BZOJ3280: 小R的烦恼
  9. 数学之路-python计算实战(19)-机器视觉-卷积滤波
  10. ACdream 1028 Path
  11. Go基础
  12. 修改文件系统属性chattr,查看文件系统属性lsattr
  13. 腾讯北京SNG一面
  14. unity零基础开始学习做游戏(五)看看你的完成度,进度条了解一下?
  15. win10安装Oracle11g-出现INS-13001环境不满足最低要求问题
  16. java开发中使用枚举表述数据字典
  17. 物理服务器Linux下软RAID和UUID方式挂载方法--Megacli64
  18. ASP.net MVC把Html Table导出Excel
  19. Container(容器)与 Injector(注入)
  20. String args[] 和 String[] args 有什么区别

热门文章

  1. web 容器
  2. linux crontab详解 php开发相关
  3. Linux中找到占用cpu最高的线程
  4. git 用远程覆盖本地
  5. Cocos 2dx项目lua调用OC出现卡死但不闪退的坑
  6. Python返回多个值
  7. 【LeetCode每天一题】Maximum Subarray(最大子数组)
  8. Python subprocess.Popen() error (No such file or directory)
  9. 关于Oracle 10.2.0.5 版本应用SCN补丁14121009相关问题
  10. windows程序设计 MessageBox消息框