数据类型检测

typeof

用来检测数据类型的运算符

语法:typeof [value]

返回值:首先是一个字符串,字符串中包含了我们需要检测的数据类型

使用typeof有自己的局限性,不能细分出当前的值是数组还是正则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typeof 12; // 'number'
typeof NaN; // 'number'
typeof ''; // 'string'
var flag = true;
typeof flag; // 'boolean'
typeof undefined; // 'undefined'

null == undefined; // true
function fn(n, m){
if (typeof n === 'undefined') {
//=> 比双等号更严谨
}
}
typeof null; // 'object' 虽然是基本数据类型值,但是他属于空对象指针,检测的结果是对象
typeof {}; // 'object'
typeof function(){}; // 'function'
typeof []; // 'object'
typeof /^$/; // 'object'
typeof 1>1?0:2; // 2
typeof (1>1?0:2); // 'number'

instanceof & constructor

instanceof:检测当前对象是否属于某一个类的实例

使用instanceof检测某个值是否是属于某一个数据类型的内置类,从而检测出它是否是这个类型值,使用instanceof可以实现typeof实现不了的对对向类型值得区分检测

【弊端】

  1. 基本类型值无法基于它检测
  2. instanceof检测的原理是基于原型链检测的,只要当前类在实例的原型链上,最后返回的结果都是true

constructor:构造函数

  1. 获取当前要检测数据值得constructor,判断当前数据是不是某一个数据类型内置类来检测
  2. 检测数据类型非常不可靠,因为这个属性经常容易被修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[] instanceof Array; // true
[] instanceof RegExp; // false

var num = 12;
num.toFixed(2); // '12.00' 12是Number类的一个实例,可以调取Number.prototype上的方法,但是他是基本类型值

var num2 = new Number(12);
num2.toFixed(); // '12.00'
typeof num2; // 'object'

//=> 不管哪一种方式创建的基本类型值,都是自己所属类的实例(只不过类型不一样而已)
num instanceof Number; // false
num2 instanceof Number; // true

var ary = [];
ary instanceof Array; // true
ary instanceof Object; // true

function Fn(){}
Fn.prototype = new Array(); // 原型继承(Fn是Array的子类)
var f = new Fn();
f instanceof Array; // true f其实不应该是数组,虽然在他的原型上可以找到数组,但是它不具备数组的基础结构,这也是instanceof的弊端

ary.constructor === Array; // true 说明ary是数组
ary.constructor === RegExp; // false
ary.constructor === Object; // false

Object.prototype.toString.call([value])

获取Object.prototype上的toString()方法,让发发中的this变为需要检测的数据类型值,并且执行这个方法

在Number/String/Boolean/Array/Function/Regexp…这些类的原型上都有一个toString方法,这个方法就是把本身的值转换为字符串

在Object这个类的原型上也有一个方法toString,但是这个方法并不是把值转换为字符串,而是返回当前值所属类的详细信息,固定结构:[object 所属的类]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(12).toString(); // '12'
(true).toString(); // 'true'
[12,23].toString(); // '12.23'
var obj = {name: 'aa'};
obj.toString(); // "[object Object]" 调取的正是Obejct.prototype.toString
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 Array]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call(/^$/); // "[object RegExp]"
Object.prototype.toString.call(function(){}); // "[object Function]"
Object.prototype.toString.call(Math); // "[object Math]"
Object.prototype.toString.call(document.body); // "[object HTMLBodyElement]"
Object.prototype.toString.call(document); // "[object HTMLDocument]"


//=> obj.toString(); 执行
//=> 执行的是Object.prototype.toString
//=> 方法中的this指向的是obj
//=> object.prototype.toString执行的时候返回的是当前方法中this所属类的信息
//=> 也就是,我们想知道谁的所属类信息,我们就把这个toString方法执行,并且让this变为我们检测的这个数据值,那么方法返回的结果就是当前检测这个值得所属累信息

使用toString检测数据类型,不管你是什么类型值,我们都可以正常检测出需要的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
~function(){
var obj = {
isNumber: 'Number',
isString: 'String',
isBoolean: 'Boolean',
isNull: 'Null',
isUndefined: 'Undefined',
isPlanObject: 'Obejct',
isArray: 'Array',
isRegExp: 'RegExp',
isFunction: 'Function'
};
var check = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var value = obj[key];
check[key] = (function(classValue){
return function(val){
return new RegExp('\\[object '+ classValue +'\\]').test(Object.prototype.toString.call(val));
}
})(obj[key]);
}
}
window.check = check;
}();