1、typeof
检测数据类型
- typeof
- instanceof
- constructor
- Object.prototype.toString.call
- 检测数据类型公共方法封装
js中的数据类型检测专题汇总
typeof
用来检测数据类型的运算符
语法:typeof[value]
返回结果:首先是一个字符串,字符串中包含了我们需要检测的数据类型
typeof 12 => 'number'
typeof Nan => 'number'
typeof '' => 'string'
var flag = true;
typeof flag => 'booleanr'
typeof undefined => 'undefined'
function fn(n,m){
if(typeof n==='undefined'){
n=0
}
}
typeof null => 'object' null虽然是基本类型值,但是它属于空对象指针,检测的结果是对象(局限性)
typeof {} => 'object'
typeof function(){} => 'function'
typeof [] => 'object'
typeof /^$/ => 'object'
//使用typeof有自己的局限性,不能具体细分出当前的值是数组还是正则(也就是不能细分对象类型的值)
typeof (1>1?0:2) => 'number'
typeof 1>1?0:2 => 2 //这里涉及到运算符优先级问题 先计算typeof 1 => 'number' => 'number'>1?0:2 所以typeof跟加减乘除问号一样属于逻辑运算符,多个运算符在一起会存在优先级问题
面试题
typeof typeof [] => 'string' //先检测typeof []得到的结果是'object',再检测typeof 'object'=>字符串
typeof是项目中非常常用的检测数据类型的方式,对于数,正则,不能细分对象类型(局限性)我们使用其他方式来做
2、instanceof和constructor
instanceof:检测某一个实例是否隶属于某个类
constructor:构造函数
使用instanceof检测某个值是否属于某一个数据类型的内置类,从而检查出它是否是这个类型的值;使用instanceof可以实现typeof实现不了的,对对象类型值详细的区分检测
[] instanceof Array => true
[] instanceof RegExp => false
使用instanceof检测也有自己的弊端:
1、基本类型值无法基于它检测
//字面量创建
var num = 12;
num.toFixed(2) => "12.00" //说明:12是Number类的一个实例,因为它可以调取Number.prototype上的方法,但是它是一个基本类型值
// 构造函数创建
var num2 = new Number(12);
num2.toFixed(2) => "12.00"
// 基本类型值通过字面量创建和构造函数创建,相同点都是Number类的一个实例,不同点一个是基本类型值,一个是引用数据类型值
typeof num => 'number'
typeof num2 => 'object'
//不管是哪一种方式创建基本类型值,都是自己所属类的实例(只不过类型不一样而已)
num instanceof Number => false
num2 instanceof Number => true
为什么instanceof能检测num2检测不到num呢?如2、
2、instanceof检测的原理是基于原型链检测的:只要当前类在实例的原型链上,最后返回的结果都是true
var ary=[];
ary instanceof Array // => true
ary instanceof Object // => true
function Fn(){}
Fn.prototype=new Array();//原型继承(Fn是Array的子类)
var f =new Fn();
console.dir(f)//打印出来的f并没有数组的length属性,不具备数据的基础结构
f instanceof Array // true 但是我们的f其实不应该是数组,虽然在它的原型上可以找到数组,但是它不具备数组的基础结构
//(数组有length属性,它没有),这也instanceof的弊端
constructor
获取当前要检测数据值的constructor,判断它是否是某一个数据类型内置类来检测
var ary=[];
ary.constructor === Array; // true
ary.constructor === RegExp; //false
ary.constructor === Object; //false
ary.constructor='AA';
ary.constructor===Array // false
// constructor检测数据类型非常不可靠,因为这个属性是经常容易被修改的
constructor检测数据类型非常不可靠,因为这个属性是经常容易被修改的
3、Object.prototype.toString
Object.prototype.toString.call([value]):获取Object.prototype上的toString方法,让方法中的this变为需要检测的数据类型值,并且让方法执行
在Number、String、Boolean、Array、Function、RegExp...这些类的原型上都有一个toString方法;这个方法就是把本身的值转换为字符串的
(12).toString // '12'
(true).toString // 'true'
[12,23].toString // '12,23'
在Obeject这个类的原型上也有一个方法toString,但是这个方法并不是把值转换为字符串,而是返回当前值的所属类详细信息,固定结构:'[object 所属的类]'
var obj = {name:'哈哈'};
obj.toString() // "[object Object]" 调取的正是Object.prototype.toString
// obj.toString()
// 首先执行Object.prototype.toString方法
// 这个方法中的this就是我们操作的数据值obj
// 总结:Object.prototype.toString执行的时候会返回当前方法中this的所属类信息
// 也就是,我想知道谁的所属类信息,我们就把这个toString方法执行,并且让this变为我们检测的这个数据值
// ,那么方法返回的结果就是当前检测这个值的所属类信息
使用toString检测数据类型,不管你是什么值,我们都可以正常检测出需要的结果(这个方法检测是万能的)
Object.prototype.toString.call([value])
({}).toString.call([value])
Object.prototype.toString.call(12) // [object Number]
Object.prototype.toString.call(true)// [object Boolean]
Object.prototype.toString.call('')// [object String]
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(/^$/)// [object RegExp]
Object.prototype.toString.call(function(){})// [object Math]
Object.prototype.toString.call(Math)// [object Function]
Object.prototype.toString.call(document.body)// [object HTMLBodyElement]
Object.prototype.toString.call(document)// [object HTMLDocument]

4、检测数据类型方法的封装
由于Object.prototype.toString检测数据类型方法写起来很长也很麻烦,所以封装一个

~function () {
var obj = {
isNumber: 'Number',
isString: 'String',
isBoolean: 'Boolean',
isNull: 'Null',
isUndefined: 'Undefined',
isPlanObject: 'Object',
isArray: 'Array',
isRegExp: 'RegExp',
isFunction: 'Function'
};
var check = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
check[key] = (function (classValue) { // 把实参obj[key]传给形参classValue 实参是传递的值,形参是接收传递的值
return function (val) {
return new RegExp('\\[object ' + classValue + '\\]').test(Object.prototype.toString.call(val));
}
})(obj[key]);
}
}
window.check = check;
}();
console.log(check);
check.isNumber(12);

