js判断数据类型

js中的数据类型

js中的数据类型大致可以分为以下几种:

  1. 基本类型:number、 string、 boolean
  2. 特殊类型:undefined、 null
  3. 引用类型:Object、 Function、 Date、 Array 等等

下面介绍js中提供的三种判断数据类型的方法

typeof

typeof 返回一个表示数据类型的字符串,返回值有 number、 string、 boolean、 undefined、 object、 function 这6种

1
2
3
4
5
6
7
8
9
10
typeof 123; // number
typeof ''; // string
typeof true; // boolean
typeof undefined; // undefined
typeof null; // object 不能正确判断出null类型
typeof new Function(); // function
typeof {}; // object
typeof []; // object 不能正确判断出数组类型
typeof new Date(); // object 不能正确判断出日期类型
typeof new RegExp(); // object 不能正确判断出正则类型

从上面的结果中可以看出 typeof 可以正确判断出基本类型,但是对于 null、Date、Array 等都是返回 object,不能得到具体的类型,使用的时候需要特别注意

instanceof

instanceof检测的是原型,可以判断 a 是否为 b 的实例, 使用方式为:a instanceof b,其内部执行过程如下

1
2
3
function instanceof(a, b) {
return a.__proto__ === b.prototype;
}

如果 a 的 __proto__ 指向 b 的 prototype 时,就认为 a 是 b 的实例

1
2
3
4
5
6
7
8
9
10
[] instanceof Array; // true
new Date() instanceof Date; // true
new RegExp() instanceof RegExp; // true
function Car() {};
new Car() instanceof Car; // true
[] instanceof Object; // true
new Date() instanceof Object; // true
new RegExp() instanceof Object; // true
new Car() instanceof Object; // true

从上面的代码可以看出,instanceof 能够判断出 [] 是 Array 的实例,但也认为 [] 是 Object 的实例,这是为什么呢?
看下面的代码就明白了

1
2
3
[].__proto__ === Array.prototype; // true
Array.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

从 [] -> Array -> Object -> null 这四者构成了一条原型链,[] 的 __proto__ 直接指向 Array.prototype,间接指向 Object.prototype,所以 [] 也是 Object 的实例,类似new Date()、new Car() 也会形成一条这样的原型链,因此,instanceof 只能用来判断两个对象是否属于原型链的关系,而不能获得对象的具体类型

Object.prototype.toString

可以通过 toString() 来获取每个对象的类型。为了每个对象都能通过 Object.prototype.toString() 来检测(这是因为大部分对象都实现了自身的 toString 方法,如果通过 [1, 2].toString() 这种方式来调用的话,是无法获取到具体类型的),需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,把需要检测的对象作为第一个参数传入

1
2
3
4
5
6
7
8
9
10
11
Object.prototype.toString.call(123); // [object Number]
Object.prototype.toString.call('abc'); // [object String]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call({}); // [object Object]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(function(){}); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]

通过上面的代码可以看出 Object.prototype.toString 基本能够准确的获取到所有对象的具体类型,事实上 jQuery 中的 type() 方法也是通过这种方式来实现的

jQuery 中 type() 方法实现源码

jQuery 中 type 方法实现源码,

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
27
28
29
30
31
32
33
// 用于预存储一张类型表用于 hook
var class2type = {};
// 原生的 typeof 方法并不能区分出一个变量它是 Array 、RegExp 等 object 类型,jQuery 为了扩展 typeof 的表达力,因此有了 $.type 方法
// 针对一些特殊的对象(例如 null,Array,RegExp)也进行精准的类型判断
// 运用了钩子机制,判断类型前,将常见类型打表,先存于一个 Hash 表 class2type 里边
"Boolean Number String Function Array Date RegExp Object Error".split(" ").forEach(function(name, i) {
class2type["[object " + name + "]"] = name.toLowerCase();
});
// 确定JavaScript 对象的类型
function type(obj) {
if (obj == null) {
return String(obj);
}
// 利用事先存好的 hash 表 class2type 作精准判断
// 这里因为 hook 的存在,省去了大量的 else if 判断
return typeof obj === "object" || typeof obj === "function" ?
class2type[Object.prototype.toString.call(obj)] || "object" :
typeof obj;
}
// example
type(123); // number
type('abc'); // string
type(true); // boolean
type(undefined); // undefined
type(null); // null
type([]); // array
type({}); // object
type(function(){}); // function
type(new Date()); // date
type(new RegExp()); // regexp

参考链接
JS 判断数据类型的三种方法
javascript判断数据类型

坚持原创技术分享,您的支持将鼓励我继续创作!