先看js的数据类型
js的数据分为原始类型和引用类型,原始类型有六种,分别是Undefined,Null,Boolean,Number、String和Symbol,引用类型有挺多种的,不过一般只记Array,function和Object
要看细节的可以去下面的链接看一下原始类型和引用类型的具体区别
https://www.cnblogs.com/sunny-shine/p/11350701.html
1、typeof
这个只能判断区分基本类型number、string、boolean、undefined、symbol和引用类型的object,function;
console.log(typeof 0) //number
console.log(typeof true)//boolean
console.log(typeof undefined)//undefined
console.log(typeof "hello world" )//string
console.log(typeof null)//object
console.log(typeof Symbol())//symbol
console.log(typeof Symbol)//function
console.log(typeof function(){})//function
console.log(typeof {})//object
console.log(typeof [])//object
这里应该可以看到了一个问题,为什么typeof判断Symbol类型的时候好像有点不太对劲,这里我找到一个博主写的关于这个问题的解答
https://www.cnblogs.com/tangjiao/p/10039659.html
下一篇我自己也会在整理一下symbol的学习笔记,希望自己能够对这个属性有更多的了解
因为typeof无法判断对象、数组和null,所以出现下一个方法
2、instanceof
instanceof用来判断A是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。instanceof检测的是原型,内部机制是通过判断对象的原型链中是否有类型的原型。
var a={};
a instanceof Object //true
a instanceof Array //false
var b=[];
b instanceof Array //true
b instanceof Object //true
因为数组属于object中的一种,所以数组b instanceof Object
也是true,但是还有一个问题,instanceof不能区分基本类型string和boolean,除非是字符串对象和布尔对象,像下面这样才行
var c='abc';
c instanceof String; //false
var d=new String();
d instanceof String //true
所以还是无法完全区分对象和数组,所以再来一个方法
3、constructor
当一个函数F被定义时,JS引擎会为F添加prototype原型,然后在prototype上添加一个constructor属性,并让其指向F的引用,F利用原型对象的constructor属性引用了自身,当F作为构造函数创建对象时,原型上的constructor属性被遗传到了新创建的对象上,从原型链角度讲,构造函数F就是新对象的类型。这样做的意义是,让对象诞生以后,就具有可追溯的数据类型。
constructor可以区分Array、Object、Function、String、Boolean和Number
var o={};
o.constructor==Object //true
o.constructor==Array //false
var arr=[];
arr.constructor==Array //true
arr.constructor==Object //false
所以还是有几个无法区分的,上面的三个方法都或多或少有点问题,所以来一个最好用的方法
4、Object.prototype.toString.call()
toString()是Object的原型方法,调用该方法,默认返回当前对象的[[Class]]。这是一个内部属性,其格式为[object Xxx],其中Xxx就是对象的类型,对于Object对象,直接调用toString()就能返回[object Object],而对于其他对象,则需要通过call、apply来调用才能返回正确的类型信息
Object.prototype.toString.call(123)//"[object Number]"
Object.prototype.toString.call('str')//"[object String]"
Object.prototype.toString.call(true)//"[object Boolean]"
Object.prototype.toString.call(null)//"[object Null]"
Object.prototype.toString.call(undefined)//"[object Undefined]"
Object.prototype.toString.call({})//"[object Object]"
Object.prototype.toString.call([])//"[object Array]"
Object.prototype.toString.call(function(){})//"[object Function]"
还有一些像window、Date、Regexp等其实也是可以判断的,所以这个方法是判断类型最好的方法
在查资料的时候发现了一些需要注意的问题:
使用instaceof和construcor,被判断的array必须是在当前页面声明的!比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,这时判断该变量,Array == object.constructor;会返回false; 原因: 1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。 2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!
以上如果是引用的,那就是我在早期复制到Typora时复制一些大佬博客的内容,忘记是谁的了,所以就直接引用没有注明是哪里引用的,各位见谅