为什么toString方法可以用来区分数组和对象?
首先大家都应该知道在javascript中只有是对象都存在toString方法,将调用该方法的值转换为字符串返回,如下:
var arr = [1, 2, 3];
console.log(arr.toString()); //1,2,3
但对象的toString方法和其他优点不同,其返回的是类似 '[object class]'的字符串
一、在js中,要想判断一个某个对象是属于哪种内置类型,最靠谱的方法就是通过Object.prototype.toString()方法
var arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr)); //[object Array]
二、Object.prototype.toString()原理:
ES3中关于Object.prototype.toString()方法的解释
15.2.4.2 Object.prototype.toString()
在toString方法被调用时,会执行下面的操作步骤:
1. 获取this对象的[[Class]]属性的值.
2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串.
3. 返回第二步的操作结果Result(2).
[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性.[[class]]为一个表明该对象类型的内部属性,其值类型为字符串。
所有内置对象的[[Class]]属性的值是由本规范定义的.所有宿主对象的[[Class]]属性的值可以是任意值,甚至可以是内置对象使用过的[[Class]]属性的值.[[Class]]属性的值可以用来判断一个原生对象属于哪种内置类型.需要注意的是,除了通过Object.prototype.toString方法之外,本规范没有提供任何其他方式来让程序访问该属性的值(查看 15.2.4.2).
也就是说,把Object.prototype.toString方法返回的字符串,去掉前面固定的"[object "和后面固定的"]",就是内部属性[[class]]的值,也就达到了判断对象类型的目的.jQuery中的工具方法$.type(),就是干这个的.
在ES3中,规范文档并没有总结出[[class]]内部属性一共有几种,不过我们可以自己统计一下,原生对象的[[class]]内部属性的值一共有10种.分别是:"Array", "Boolean", "Date", "Error", "Function", "Math", "Number","Object", "RegExp", "String".
es5中关于Object.prototype.toString()方法的解释
在ES5.1中,除了规范写的更详细一些以外,Object.prototype.toString方法和[[class]]内部属性的定义上也有一些变化,Object.prototype.toString方法的规范如下:
15.2.4.2 Object.prototype.toString ( )
在toString方法被调用时,会执行下面的操作步骤:
- 如果this的值为undefined,则返回
"[object Undefined]".- 如果this的值为null,则返回
"[object Null]".- 让O成为调用ToObject(this)的结果.
- 让class成为O的内部属性[[Class]]的值.
- 返回三个字符串"[object ", class, 以及 "]"连接后的新字符串
.
可以看出,比ES3多了1,2,3步.第1,2步属于新规则,比较特殊,因为"Undefined"和"Null"并不属于[[class]]属性的值,需要注意的是,这里和严格模式无关(大部分函数在严格模式下,this的值才会保持undefined或null,非严格模式下会自动成为全局对象).第3步并不算是新规则,因为在ES3的引擎中,也都会在这一步将三种原始值类型转换成对应的包装对象,只是规范中没写出来.ES5中,[[Class]]属性的解释更加详细:
所有内置对象的[[Class]]属性的值是由本规范定义的.所有宿主对象的[[Class]]属性的值可以是除了"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String"之外的的任何字符串.[[Class]]内部属性是引擎内部用来判断一个对象属于哪种类型的值的.需要注意的是,除了通过Object.prototype.toString方法之外,本规范没有提供任何其他方式来让程序访问该属性的值(查看 15.2.4.2).
和ES3对比一下,第一个差别就是[[class]]内部属性的值多了两种,成了12种,一种是arguments对象的[[class]]成了"Arguments",而不是以前的"Object",还有就是多个了全局对象JSON,它的[[class]]值为"JSON".第二个差别就是,宿主对象的[[class]]内部属性的值,不能和这12种值冲突,不过在支持ES3的浏览器中,貌似也没有发现哪些宿主对象故意使用那10个值.
参考文章:http://www.cnblogs.com/ziyunfei/archive/2012/11/05/2754156.html
为什么toString方法可以用来区分数组和对象?的更多相关文章
- reduce方法简单实现数组中对象去重
js数组的reduce方法,接收一个函数(必须)和指定的初始值(非必须)作为参数,函数有三个参数,分别为初始值,当前项,当前数组,进行累加或者累积操作,初始值为每次累加或者累计后的结果 注意:在ie9 ...
- [Effective JavaScript 笔记]第58条:区分数组对象和类数组对象
示例 设想有两个不同类的API.第一个是位向量:有序的位集合 var bits=new BitVector(); bits.enable(4); bits.enable([1,3,8,17]); bi ...
- 优雅的重载toString方法,打印对象内容而不是打印内存地址的方法
如果直接在日志或者System.out.println中打印java对象,会打印这个对象的内存地址,而不是具体内容. 为了便于调试,一般的做法有2种: 1.重写toStrong方法 2.将对象传入JS ...
- Java对象toString()方法
对象的字符串表示以可读格式包含有关对象状态的信息.Object类的toString()方法表示字符串中类的对象.Object类提供了toString()方法的默认实现. 它返回一个以下格式的字符串: ...
- 从toString()方法到Object.prototype.toString.call()方法
一.toString方法和Object.prototype.toSting.call()的区别 var arr=[1,2]; 直接对一个数组调用toString()方法, console.log(ar ...
- toString()方法
前面的话 本文将介绍toString()方法,toString()方法返回反映这个对象的字符串 [1]undefined和null没有toString()方法 undefined.toString() ...
- js 判断 数组和对象
提方案的时候顺便会引申一下该方法的使用. 一,instanceOf:(可以判断) instanceOf运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性. 也可以这样说 ...
- 为何重写toString方法后会使哈希码能够打印出来
首先还是推荐lz看源代码 简单的讲之所以调用了toString()方法,不是什么编译器默认的,而是因为lz你调用的是out.print()方法仔细看源代码,在PringStream类中,print方法 ...
- Object类中通用方法之:toString()方法
1.Java所有的对象都是Object类的实例,都可以直接调用该类中定义的方法,这些方法称为通用方法 2.toString()方法即为Object类中定义的通用方法之一 3.平时我们如果在控制台直接打 ...
随机推荐
- c++基础(一):数据类型和结构
1.map map<int, int> rankDict;//定义map rankDict[1] = 5; rankDict[2] = 6;//map赋值 int dictSize = r ...
- LintCode-Implement Queue by Stacks
As the title described, you should only use two stacks to implement a queue's actions. The queue sho ...
- ios-UIWebView中js和oc代码的互调
webview是ios中显示远程数据的网页控件,webview能显示的内容很多,MP4.文本.pdf等等: 关于js和oc代码的互相调用 1:oc中调用js代码; >>oc中调用js代码很 ...
- ORM 框架
1.Dapper 2.Entity Framework(EF) http://www.cnblogs.com/n-pei/archive/2011/09/06/2168433.html
- 三张图看遍Linux 性能监控、测试、优化工具
Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的.简单的小工具.系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 ...
- android 开发 drawerlayout出现退不回去的情况
问题原因: id_framelayout2 写在 id_linearlayout2 的后面了: 注意记得写: android:layout_gravity="start" 正确: ...
- 利用glassfish4任意文件读取拿权限的一些思路
只要讨论的是linux环境测试发现只针对GlassFish4,且基本上是已root运行的http://www.wooyun.org/bugs/wooyun-2010-0144595 zoomeye d ...
- 安装Symfony2
我就不明白这个框架明明很小就几M,为什么这么难下载. 他们为什么不把文件打包好?非要搞得这么复杂. 一开始我在Linux ubuntu下载没有成功 然后想在win10上试试 到www.apache.o ...
- LightOJ 1140 How Many Zeroes
题意:写出一个给定区间的每个数,求出一共写了多少个零. 解法:数位DP,定义dp[len][flag][num]:len的定义为数位的长度,flag定义为前导0和没有前导0的两种状态,num定义为写的 ...
- Android本地服务
一.服务生命周期总结 (一).单独开启服务,并没有绑定服务Activity中调用startService(),服务的lifecycle:onCreate()→onStartCommand()→onSt ...