摘要:不管是什么类型的,Object.prototype.toString.call();都可以判断出其具体的类型,简单基本类型(String、Number、Boolean、Null、Undefined)不是对象,复杂基本类型都为对象子类型,函数是特殊的对象子类型(可调用对象)
数据类型分为基本类型和引用类型:
基本类型:String、Number、Boolean、Null、Undefined、symbol(ES6)
引用类型:Object、Array、Date、Function、Error、RegExp、Math、Number、String、Boolean、Globle。
js内置类型有七种:String、Number、Boolean、Null、Undefined、Symbol(ES6)、Object
判断数据类型的方法一般可以通过:typeof、instanceof、constructor、Object.prototype.toString.call();四种常用方法
1、typeof:(可以对基本类型(包括function)做出准确的判断,但对于引用类型,用它就有点力不从心了)
typeof 返回一个表示数据类型的字符串,返回结果包括:number、boolean、string、object、undefined、function、Symbol6种数据类型。
对于引用类型,返回的都是object,其实返回object也没有错,因为所有对象的原型链最终都指向了Object,Object是所有对象的`祖宗`。 但当我们需要知道某个对象的具体类型时,typeof 就显得有些力不从心了。
注意:typeof null也是返回object,这是一个bug因为不同的对象在底层都是二进制存储,js中二进制前三位为0的话会被判断为object类型,而null的二进制都是0,造成误判。
2、instanceof(判断是否是某个类的实例)
判断对象和构造函数在原型链上是否有关系,如果有关系,返回真,否则返回假
function Aaa(){ } var a1 = new Aaa(); console.log( a1 instanceof Aaa); //true判断a1和Aaa是否在同一个原型链上,是的话返回真,否则返回假 var arr = []; console.log( arr instanceof Aaa);//false
我们来看一下
var str = ‘hello‘; alert(str instanceof String);//false var bool = true; alert(bool instanceof Boolean);//false var num = 123; alert(num instanceof Number);//false var nul = null; alert(nul instanceof Object);//false var und = undefined; alert(und instanceof Object);//false var oDate = new Date(); alert(oDate instanceof Date);//true var json = {}; alert(json instanceof Object);//true var arr = []; alert(arr instanceof Array);//true var reg = /a/; alert(reg instanceof RegExp);//true var fun = function(){}; alert(fun instanceof Function);//true var error = new Error(); alert(error instanceof Error);//true
从上面的运行结果我们可以看到,基本数据类型是没有检测出他们的类型,但是我们使用下面的方式创建num、str、boolean,是可以检测出类型的:
var num = new Number(123); var str = new String(‘abcdef‘); var boolean = new Boolean(true); console.log(num instanceof Number) console.log(num instanceof String)
3、constructor:查看对象对应的构造函数
constructor 在其对应对象的原型下面,是自动生成的。当我们写一个构造函数的时候,程序会自动添加:构造函数名.prototype.constructor = 构造函数名
function Aaa(){ } //Aaa.prototype.constructor = Aaa; //每一个函数都会有的,都是自动生成的 //Aaa.prototype.constructor = Aaa;
判断数据类型的方法
var str = ‘hello‘; alert(str.constructor == String);//true var bool = true; alert(bool.constructor == Boolean);//true var num = 123; alert(num.constructor ==Number);//true // var nul = null; // alert(nul.constructor == Object);//报错 //var und = undefined; //alert(und.constructor == Object);//报错 var oDate = new Date(); alert(oDate.constructor == Date);//true var json = {}; alert(json.constructor == Object);//true var arr = []; alert(arr.constructor == Array);//true var reg = /a/; alert(reg.constructor == RegExp);//true var fun = function(){}; alert(fun.constructor ==Function);//true var error = new Error(); alert(error.constructor == Error);//true
从上面的测试中我们可以看到,undefined和null是不能够判断出类型的,并且会报错。因为null和undefined是无效的对象,因此是不会有constructor存在的
同时我们也需要注意到的是:使用constructor是不保险的,因为constructor属性是可以被修改的,会导致检测出的结果不正确
function Aaa(){ } Aaa.prototype.constructor = Aaa;//程序可以自动添加,当我们写个构造函数的时候,程序会自动添加这句代码 function BBB(){} Aaa.prototype.constructor = BBB;//此时我们就修改了Aaa构造函数的指向问题 alert(Aaa.construtor==Aaa);//false
可以看出,constructor并没有正确检测出正确的构造函数
备注:使用Object.create()创建的js对象,没有constructor
null和undefined没有相应的构造形式,而Date,只有相应的构造形式而没有文字形式两者相反
4、Object.prototype.toString(可以说不管是什么类型,它都可以立即判断出)
简单原理为:子类型在内部借用了object中的tostring()方法
toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,更严格的讲,是 toString运行时this指向的对象类型, 返回的类型
格式为[object xxx],xxx是具体的数据类型,其中包括:
String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,... 基本上所有对象的类型都可以通过这个方法获取到。
var str = ‘hello‘; console.log(Object.prototype.toString.call(str));//[object String] var bool = true; console.log(Object.prototype.toString.call(bool))//[object Boolean] var num = 123; console.log(Object.prototype.toString.call(num));//[object Number] var nul = null; console.log(Object.prototype.toString.call(nul));//[object Null] var und = undefined; console.log(Object.prototype.toString.call(und));//[object Undefined] var oDate = new Date(); console.log(Object.prototype.toString.call(oDate));//[object Date] var json = {}; console.log(Object.prototype.toString.call(json));//[object Object] var arr = []; console.log(Object.prototype.toString.call(arr));//[object Array] var reg = /a/; console.log(Object.prototype.toString.call(reg));//[object RegExp] var fun = function(){}; console.log(Object.prototype.toString.call(fun));//[object Function] var error = new Error(); console.log(Object.prototype.toString.call(error));//[object Error]
从这个结果也可以看出,不管是什么类型的,Object.prototype.toString.call();都可以判断出其具体的类型。
接下来我们分析一下四种方法各自的优缺点
从上表中我们看到了,instanceof和constructor不能跨iframe,上面没有细说,所以下面我们直接上例子喽
例:跨页面判断是否是数组
window.onload = function(){ var oF = document.createElement(‘iframe‘); document.body.appendChild( oF ); var ifArray = window.frames[0].Array; var arr = new ifArray(); //alert( arr.constructor == Array ); //false //alert( arr instanceof Array ); //false alert( Object.prototype.toString.call(arr) == ‘[object Array]‘ ); //true };
从结果中可以看出,constructor和instanceof都没有正确的判断出类型,只有object.prototype.toString.call();正确判断出了
其实面试官也经常喜欢让说一种最简单的判断是数组的方法,记住喽是object.prototype.toString.call()哦!
原文地址:https://www.cnblogs.com/wangtong111/p/11286925.html