前端之路 — JavaScript 准确判断数据类型的方法

2,386 阅读3分钟

JavaScript 中常见的几种数据类型:

基本类型:string,number,boolean,Symbol

特殊类型:undefined,null

引用类型:Object,Function,Function,Array,Date,...


1、typeof

typeof '';               // string 有效
typeof 1;                // number 有效
typeof true;             // boolean 有效
typeof undefined;        // undefined 有效
typeof null;             // object 无效
typeof [] ;              // object 无效
typeof new Function();   // function 有效
typeof new Date();       // object 无效
typeof new RegExp();     // object 无效

JavaScript 里 使用 typeof 来判断数据类型,只能区分基本类型,即 “ number ” , “ string ” , “ undefined ” , “ boolean ” , “ object ” 五种。

对于数组、函数、对象来说,其关系错综复杂,使用 typeof 都会统一返回 “object” 字符串。

所以,要想区别对象、数组、函数单纯使用 typeof 是不行的 ,JavaScript 中,通过 Object.prototype.toString 方法,判断某个对象值属于哪种内置类型。


2、Object.prototype.toString$.type()

console.log(Object.prototype.toString.call(123))          // [object Number]
console.log(Object.prototype.toString.call('123'))        // [object String]
console.log(Object.prototype.toString.call(undefined))    // [object Undefined]
console.log(Object.prototype.toString.call(true))         // [object Boolean]
console.log(Object.prototype.toString.call({}))           // [object Object]
console.log(Object.prototype.toString.call([]))           // [object Array]
console.log(Object.prototype.toString.call(function(){})) // [object Function]
console.log(Object.prototype.toString.call(this));        // [object Window]

判断是否为函数:

function isFunction(it) {
    return Object.prototype.toString.call(it) === '[object Function]';
}

判断是否为数组:

function isArray(o) { 
    return Object.prototype.toString.call(o) === '[object Array]';  
}

到这里不得不说 Object.prototype.toString.call() 真是判断数据类型的**"万精油"**呀!(绝招不一定要放在最后/doge/)

在 Object.prototype.toString 方法被调用时,会执行下面的操作步骤(了解):

  1. 获取this对象的[[Class]]属性的值。

  2. 计算出三个字符串"[object ", 第一步的操作结果Result(1), 以及 "]"连接后的新字符串.

  3. 返回第二步的操作结果Result(2)。

[[Class]]是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性。在规范中,[[Class]]是这么定义的:

内部属性 描述
[[Class]] 一个字符串值,表明了该对象的类型。

重点: [[Class]] 表明了该对象的类型

读到这里,你就已经掌握了准确判断数据类型的方法了,是不是感觉自己有进步了呢。

或许你用过 jQuery 的 $.type() 方法判断数据类型,其实它就是对 Object.prototype.toString.call() 的一个封装,还有在 vue-router 的源码等地方里也用来转换和检测数据类型。


当然,判断数据类型不止于以上这3种方法(typeof,Object.prototype.toString,$.type()),还有 instanceof 和 constructor 进行数据类型判断,不过他们都存在一些缺点。

3、instanceof

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false  
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true

// 这俩比较特殊,稍作解释
// console.log(undefined instanceof Undefined);
// console.log(null instanceof Null);

以上结果显示,直接的字面量值判断数据类型,只有引用数据类型(Array,Function,Object)被精准判断,其他(数值Number,布尔值Boolean,字符串String)字面值不能被instanceof精准判断。

我们来看一下 instanceof 在 MDN 中的解释:instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。其意思就是判断对象是否是某一数据类型(如Array)的实例,请重点关注一下是判断一个对象是否是数据类型的实例。在这里字面量值,2, true ,'str'不是实例,所以判断值为false。眼见为实,看下面的例子:

console.log(new Number(2) instanceof Number)      // true
console.log(new Boolean(true) instanceof Boolean) // true
console.log(new String('str') instanceof String)  // true

字面值被实例化了,他们的判断值变为了 true 。

接着,我们看一下 undefined 和 null ,说说为什么这两货比较特殊,实际上按理来说,null的所属类就是Null,undefined就是Undefined,但事实并非如此。控制台输出如下结果:

console.log(new undefined instanceof Undefined)
// TypeError: undefined is not a constructor
console.log(new null instanceof Null)
// TypeError: null is not a constructor

浏览器认为null,undefined不是构造器。但是在 typeof 中你可能已经发现了,typeof null的结果是object,typeof undefined的结果是undefined ,这是怎么回事呢 ? 其实这是 JavaScript 设计者的一大重大失误, Google公司开发的JavaScript语言的替代品Dart语言,就明确规定只有null,没有undefined!

想了解 undefined 和 null 的区别 可以看下 阮一峰大神的网络日志: www.ruanyifeng.com/blog/2014/0…


4、constructor

console.log((2).constructor === Number);                // true
console.log((true).constructor === Boolean);            // true
console.log(('str').constructor === String);            // true
console.log(([]).constructor === Array);                // true
console.log((function() {}).constructor === Function);  // true
console.log(({}).constructor === Object);               // true

用costructor来判断类型看起来是完美的,然而,如果我创建一个对象,更改它的原型,这种方式也变得不可靠了。

function Fn(){};
 
Fn.prototype = new Array();

var f = new Fn();
console.log(f.constructor === Fn);    // false
console.log(f.constructor === Array); // true

如此轻易的更改了contructor,说明了什么, Object.prototype.toString.call() 真香,/doge/。

以上就是我对 JavaScript 数据类型判断的一个学习总结了,大家加油!

ps:广州有坑位请联系我邮箱 2412684394@qq.com ,欢迎骚扰。