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

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

Js代码  收藏代码
  1. alert(typeof null); // "object"
  2. alert(typeof []); // "object"

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

Js代码  收藏代码
  1. var arr = [];
  2. alert(arr instanceof Array); // true

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

Js代码  收藏代码
  1. var arr = [];
  2. alert(arr.constructor == Array); // true

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

Js代码  收藏代码
  1. var iframe = document.createElement('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代码  收藏代码
  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代码  收藏代码
  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代码  收藏代码
  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等等,都计划借鉴此方法以实现某些特殊的,比如数组、正则表达式等对象的类型判定,不用我们自己写了。

转载于:https://www.cnblogs.com/wyf-gis/p/4065092.html

Object.prototype.toString.call()检测相关推荐

  1. 数据类型的判断 --Object.prototype.toString.call(obj)精准检测对象类型

    数据类型的判断 typeof typeof返回一个表示数据类型的字符串,返回结果包括:number.boolean.string.symbol.object.undefined.function等7种 ...

  2. 为什么用Object.prototype.toString.call(obj)检测对象类型?

    37 Essential JavaScript Interview Questions*,中有一道javascript题: 使用 typeof bar === "object" 检 ...

  3. 【javaScript】Object.prototype.toString.call() 、 instanceof 以及 Array.isArray() 区别与优化层面的比较

    1. Object.prototype.toString.call() 每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写的话,会返回 [Object ...

  4. 通过 Object.prototype.toString.call() 进行类型判断

    为什么80%的码农都做不了架构师?>>>    首先看一段ECMA中对Object.prototype.toString的解释: Object.prototype.toString( ...

  5. JavaScript:Object.prototype.toString进行数据类型判定

    在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. var arr = []; console.log(Obje ...

  6. JavaScript中Object.prototype.toString方法的原理

    在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. <一>, ECMAScript 3  1. 在E ...

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

    在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. var arr = []; console.log(Obje ...

  8. 由Object.prototype.toString.call( )引发关于toString( )方法的思考

    引言 前端面试中有这么一道经典的问题,如何判断一个对象是否为数组? ES5提供了一个确定对象是否为数组的函数 Array.isArray(object); 复制代码 其中,object是必须的,表示要 ...

  9. 关于 Object.prototype.toString.call() 方法

    Javascript中可通过typeof来获取对象的类型,但是对象如果是内置的继承Object的类型,typeof也只能返回object,不能获取对象的具体类型,如Date,Array,Boolean ...

最新文章

  1. 【算法学习笔记】二叉树的基本操作实现和应用举例,根据先序与中序遍历建立二叉树的实现
  2. 帝国CMS7.5仿《问答库》题库问答学习平台网站源码 带手机版
  3. 【idea基础知识】project structure中没有web 或没有spring
  4. echarts scatter
  5. DiscuzNT改造-远程图片自动采集-DNT2.5(自动采集、源码下载)
  6. 对分类型变量,进行编码处理——pd.get_dummies()、LabelEncoder()、oneHotEncoder()
  7. 数据仓库建设思维导图
  8. KVM虚拟化平台的基础知识及搭建部署!
  9. 计算机web二级考试内容,2015年全国计算机二级Web考试内容
  10. 句子重写任务近年有哪些值得关注的工作?看这一篇就够了!
  11. 解决:Unhandled exception in XX.exe: 0xc00000FD; Stack Overflow
  12. zbrush常用笔刷_zbrush笔刷大合集
  13. grasshopper python可以做什么_Grasshopper 有哪些奇技淫巧?
  14. 【Web 基础】Cookie
  15. Editor.md安装使用(markdown)
  16. 一款网盘搜索神器 + 某度网盘不限速下载软件
  17. 小程序滚动穿透解决方案
  18. Android稳定性系列2 ANR触发原理
  19. 基于ssm+vue的综合项目 健康体检管理系统-第六章---移动端体检预约
  20. 工科除计算机之外好专业,2018前景最好的工科专业 国内十大最好工科专业排名...

热门文章

  1. F1 score的意义
  2. python对异常_关于python中的异常
  3. mysql 5.1 innodb trx_mysql 优化innodb_flush_log_at_trx_commit的案例介绍
  4. php入门的ppt,php学习 字符串课件
  5. IT项目经理学习-德鲁克时间管理
  6. Openlayers中多图层遮挡时调整图层上下顺序
  7. Webservice入门教程_用CXF编写基于Spring的WebService
  8. MyBatisPlus条件构造器带条件查询selectList使用
  9. Bootstrap模态框(modal)显示、隐藏与禁用ESC代码实现
  10. 计算机网络总结:第二章 应用层