判断js中的数据类型有一下几种方法:typeof、instanceof、 constructor、 prototype,接下来主要比较一下这几种方法的异同。
首先写一个测试用例:
let test = {
num: 0,
str: '',
boolean: true,
unf: undefined,
nul: null,
symbol:Symbol(),
obj: {
name: '我是一个对象',
id: 1
},
arr: [0, 1, 2],
func: function() {
console.log('我是一个函数')
},
date: new Date(0),
reg: new RegExp('/我是一个正则/ig'),
err: new Error('我是一个错误')
}
1、最常见的判断方法:typeof
alert(typeof test.num) ------------> number
alert(typeof test.str) ------------> string
alert(typeof test.boolean) ------------> boolean
alert(typeof test.unf) ------------> object
alert(typeof test.nul) ------------> object
alert(typeof test.symbol) ------------> symbol
alert(typeof test.obj) ------------> object
alert(typeof test.arr) ------------> object
alert(typeof test.func) ------------> function
alert(typeof test.date) ------------> object
alert(typeof test.reg) ------------> object
alert(typeof test.err) ------------> object
typeof返回的类型都是字符串形式
2、判断已知对象类型的方法: instanceof
语法:object instanceof constructor
alert(test.obj instanceof Object) ---------------> true
alert(test.arr instanceof Array) ---------------> true
alert(test.date instanceof Date) ------------> true
alert(test.func instanceof Function) ------------> true
alert(test.reg instanceof RegExp)) ------------> true
alert(test.err instanceof Error)) ------------> true
alert(test.num instanceof function) ------------> false
注意:instanceof 后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。
3、根据对象的constructor判断: constructor
alert(test.obj.constructor === Object) ----------> true
alert(test.arr.constructor === Array) -----------> true
alert(test.data.constructor === Date) -------> true
alert(test.func.constructor === Function) -------> true
注意: constructor 在类继承时会出错,例如:
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:
alert(aobj instanceof B) ----------------> true;
alert(aobj instanceof B) ----------------> true;
言归正传,解决construtor的问题通常是让对象的constructor手动指向自己:
aobj.constructor = A; //将自己的类赋值给对象的constructor属性
alert(aobj.constructor === A) -----------> true;
alert(aobj.constructor === B) -----------> false; //基类不会报true了;
4、通用但很繁琐的方法: prototype
alert(Object.prototype.toString.call(test.num) === '[object Number]') -------> true;
alert(Object.prototype.toString.call(test.str) === '[object String]') -------> true;
alert(Object.prototype.toString.call(test.boolean) === ‘[object Boolean]') -------> true;
alert(Object.prototype.toString.call(test.unf) === '[object Undefined]') -------> true;
alert(Object.prototype.toString.call(test.nul) === '[object Null]') -------> true;
alert(Object.prototype.toString.call(test.symbol) === '[object Symbol]') -------> true;
alert(Object.prototype.toString.call(test.obj) === '[object Object]') -------> true;
alert(Object.prototype.toString.call(test.arr) === '[object Array]') -------> true;
alert(Object.prototype.toString.call(test.func) === '[object Function]') -------> true;
alert(Object.prototype.toString.call(test.date) === '[object Date]') -------> true;
alert(Object.prototype.toString.call(test.reg) === '[object RegExp]') -------> true;
alert(Object.prototype.toString.call(test.err) === '[object Error]') -------> true;
大小写不能写错,比较麻烦,但胜在通用。