使用typeof bar === "object"检测”bar”是否为对象有什么缺点?如何避免?这是一个十分常见的问题,用 typeof 是否能准确判断一个对象变量,答案是否定的,null 的结果也是 object,Array 的结果也是 object,有时候我们需要的是 "纯粹" 的 object 对象。如何避免呢?比较好的方式是:

console.log(Object.prototype.toString.call(obj) === "[object Object]");

使用以上方式可以很好的区分各种类型:

(无法区分自定义对象类型,自定义类型可以采用instanceof区分)

console.log(Object.prototype.toString.call("jerry"));//[object String]
console.log(Object.prototype.toString.call(12));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "jerry"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));//[object Object]

为什么这样就能区分呢?于是我去看了一下toString方法的用法:toString方法返回反映这个对象的字符串。

那为什么不直接用obj.string()呢?

console.log("jerry".toString());//jerry
console.log((1).toString());//1
console.log([1,2].toString());//1,2
console.log(new Date().toString());//Wed Dec 21 2016 20:35:48 GMT+0800 (中国标准时间)
console.log(function(){}.toString());//function (){}
console.log(null.toString());//error
console.log(undefined.toString());//error

同样是检测对象obj调用toString方法(关于toString()方法的用法的可以参考toString的详解),obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

这是因为toString为Object的原型方法,而Array ,function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object上原型toString方法。

我们可以验证一下,将数组的toString方法删除,看看会是什么结果:

var arr=[1,2,3];
console.log(Array.prototype.hasOwnProperty("toString"));//true
console.log(arr.toString());//1,2,3
delete Array.prototype.toString;//delete操作符可以删除实例属性
console.log(Array.prototype.hasOwnProperty("toString"));//false
console.log(arr.toString());//"[object Array]"

删除了Array的toString方法后,同样再采用arr.toString()方法调用时,不再有屏蔽Object原型方法的实例方法,因此沿着原型链,arr最后调用了Object的toString方法,返回了和Object.prototype.toString.call(arr)相同的结果。


各种判断类型的方法汇总

1、最常见的判断方法:typeof

1
2
3
4
5
6
alert(typeof a)  ------------> string
alert(typeof b)  ------------> number
alert(typeof c)  ------------> object
alert(typeof d)  ------------> object
alert(typeof e)  ------------> function
alert(typeof f)  ------------> function

其中typeof返回的类型都是字符串形式,需注意,例如:

1
2
alert(typeof a == "string") -------------> true
alert(typeof a == String) ---------------> false

另外typeof 可以判断function的类型;在判断除Object类型的对象时比较方便。 

2、判断已知对象类型的方法: instanceof

1
2
3
4
alert(c instanceof Array) ---------------> true
alert(d instanceof Date)
alert(f instanceof Function) ------------> true
alert(f instanceof function) ------------> false

注意:instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。  

3、根据对象的constructor判断: constructor

alert(c.constructor === Array) ----------> true
alert(d.constructor === Date) -----------> true
alert(e.constructor === Function) -------> true

注意: constructor 在类继承时会出错

eg:

1
2
3
4
5
6
function A(){};
function B(){};
A.prototype = new B(); //A继承自B
var aObj = new A();
alert(aobj.constructor === B) -----------> true;
alert(aobj.constructor === A) -----------> false;

而instanceof方法不会出现该问题,对象直接继承和间接继承的都会报true:

1
2
alert(aobj instanceof B) ----------------> true;
alert(aobj instanceof B) ----------------> true;

言归正传,解决construtor的问题通常是让对象的constructor手动指向自己:

1
2
3
aobj.constructor = A; //将自己的类赋值给对象的constructor属性
alert(aobj.constructor === A) -----------> true;
alert(aobj.constructor === B) -----------> false; //基类不会报true了;

4、通用但很繁琐的方法: prototype

1
2
3
4
5
6
alert(Object.prototype.toString.call(a) === ‘[object String]') -------> true;
alert(Object.prototype.toString.call(b) === ‘[object Number]') -------> true;
alert(Object.prototype.toString.call(c) === ‘[object Array]') -------> true;
alert(Object.prototype.toString.call(d) === ‘[object Date]') -------> true;
alert(Object.prototype.toString.call(e) === ‘[object Function]') -------> true;
alert(Object.prototype.toString.call(f) === ‘[object Function]') -------> true;

大小写不能写错,比较麻烦,但胜在通用。

图形验证码知识点整理 Object.prototype.toString.call()等的更多相关文章

  1. Object.prototype.toString.call(obj)使用方法以及原理

    这几天看vue-router的源码 发现了Object.prototype.toString.call()这样的用法,当时以为这就是转成字符串的用的,但是越看越觉得不太对劲,赶紧查查资料,一查才知道没 ...

  2. typeof 、Object.prototype.toString和 instanceof

    数据类型 js 基本类型包括:Undefined  symbol null string boolean number js 引用类型包括:object array Date RegExp typeo ...

  3. 利用Object.prototype.toString方法,实现比typeof更准确的type校验

    Object.prototype.toString方法返回对象的类型字符串,因此可以用来判断一个值的类型. 调用方法: Object.prototype.toString.call(value) 不同 ...

  4. instanceof, typeof, & Object.prototype.toString

    /** * * @authors Your Name (you@example.org) * @date 2016-11-18 09:31:23 * @version $Id$ */instanceo ...

  5. 判断一个变量的类型Object.prototype.toString.call

    var num = 1;alert(Object.prototype.toString.call(num)); // [object Number]var str = 'hudidit.com';al ...

  6. Object.prototype.toString.call() 区分对象类型

    判断一个对象的类型: /** * 判断对象是否为数组 * @param {Object} source 待判断的对象 * @return {Boolean} true|false */ Object. ...

  7. Object.prototype.toString.call()进行类型判断

    为什么类型判断用到Object.prototype.toString.call()进行类型判断,而不用typeof()呢? 然后翻了一下资料: Typeof 在使用 ]));/));));//[obj ...

  8. toStirng()与Object.prototype.toString.call()方法浅谈

    一.toString()是一个怎样的方法?它是能将某一个值转化为字符串的方法.然而它是如何将一个值从一种类型转化为字符串类型的呢? 通过下面几个例子,我们便能获得答案: 1.将boolean类型的值转 ...

  9. JavaScript中toStirng()与Object.prototype.toString.call()方法浅谈

    toStirng()与Object.prototype.toString.call()方法浅谈 一.toString()是一个怎样的方法?它是能将某一个值转化为字符串的方法.然而它是如何将一个值从一种 ...

随机推荐

  1. RTMPdump(libRTMP) 源代码分析 10: 处理各种消息(Message)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  2. SharePoint 2013 页面访问,Url中间多一段"_layouts/15/start.aspx#"

    问题描述: 我想访问如下页面 http://Host/_layouts/15/ManageFeatures.aspx 点击以后页面地址没有错,但是中间多了一段"_layouts/15/sta ...

  3. spring+mybaits多数据源使用

    一.在利用spring管理mybatis时可以同时配置多个数据源,并且数据源可以随时切换,但在多线程中多数据源的事务需要一定的配置. 多数据源配置: <bean id="postgre ...

  4. PHP变量的定义与相应的数据类型

    在PHP中,变量的定义和C语言定义的方法是类似的,但是在PHP中,变量使用起来就非常灵活,一个变量既可以做整型,也可以是浮点型,也可以是字符串或者字符类型,通通只要在变量名前面加一个$然后加上你的变量 ...

  5. prototype.js 和json.js 冲突

    1.冲突简述和分析 prototype.js与json.js并不是完全兼容的.主要冲突在于json.js为Object的原型增加了一个toJSONString的方法. 冲突之一:是prototype中 ...

  6. Spring Boot 添加jersey-mvc-freemarker依赖后内置tomcat启动不了解决方案

    我在我的Spring Boot 项目的pom.xml中添加了jersey-mvc-freemarker依赖后,内置tomcat启动不了. 报错信息如下: org.springframework.con ...

  7. java原子操作

    一.何谓Atomic? Atomic一词跟原子有点关系,后者曾被人认为是最小物质的单位.计算机中的Atomic是指不能分割成若干部分的意思.如果一段代码被认为是Atomic,则表示这段代码在执行过程中 ...

  8. iOS Swift开发的一些坑

    0.人难招,特别是对于没钱的小团队,大多数的iOS开发者没有Swift经验,有经验的也并不是很深入 0.1.语言unwrap坑,虽然有自动修正提示,但感觉代码过程不流畅. 1.Realm的缺憾: 最近 ...

  9. 关于Python的super用法研究

    一.问题的发现与提出 在Python类的方法(method)中,要调用父类的某个方法,在python 2.2以前,通常的写法如代码段1: 代码段1: class A:  def __init__(se ...

  10. mybatis源码解读(三)——数据源的配置

    在mybatis-configuration.xml 文件中,我们进行了如下的配置: <!-- 可以配置多个运行环境,但是每个 SqlSessionFactory 实例只能选择一个运行环境常用: ...