1.使用 typeof 进行类型检测

可以看到,在上面的类型检测中 number、string、undefined、boolean、对象,都是正确的,但是数组、null,都是 object 类型

这也就引出了 typeof 判断类型的两个弊端,typeof 不能用于检测 数组和null。

那要如何解决呢?

(1)使用 === 来判断 null 的类型

首先,先理解一下,为什么 null 会显示出 object 类型呢,这是因为 JavaScript 的历史遗留问题,早期 JS 使用低位二进制表示类型,null 的值被表示为全 0,而对象的类型标识也是 0,导致 typeof null 被错误识别为 object

通过使用 === 可以清楚的知道 null 的类型。

(2)使用 Array.isArray() 来判断 数组 的类型

isArray() 是 Array 构造函数的一个静态方法。

2.使用 instanceof 来判断类型

instanceof 之所以可以用来判断类型,其运行机制是会去判断当前值在其原型链上中能否找到该类型的原型
可以看到,instanceof 只能正确判断引用数据类型,而不能判断基本数据类型。(基本数据类型没有原型链)instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

3.使用 constructor 来判断类型

constructor 有两个作用:一是判断数据的类型,二是对象实例通过 constructor 可以访问到其构造函数。需要注意,如果创建一个对象来改变它的原型,constructor 就不能用来判断数据类型了。

需要注意的是:

  • constructor 可被手动修改

  • Object.create(null) 创建的对象 没有 constructor

  • 因此 constructor 并不安全,不能作为可靠的类型判断依据。


 

4.判断类型的终极解决方案:Object.prototype.toString.call()

这里首先要弄清楚几个问题:

第一:为什么不能使用其他类型的原型上的 toSting() 方法,而要使用 Object 原型上的 toString() 方法?

回答:首先要知道,toString() 方法是 Object 原型上的方法,那么在使用其他类型原型上的 toString() 方法会导致该方法被重写,从而作用改变成将传入的值转为 string 类型,而只有使用 Object 原型上的 toString() 方法保留了规范定义的行为,返回内部类型标签

第二:为什么 Object 原型上的 toString() 可以进行类别判断呢,这不是一个转字符串的方法吗?

回答:Object.prototype.toString() 之所以能判断类型,是因为它直接读取 JavaScript 引擎维护的内部类型标签,而不是基于原型链或构造函数推断类型。

第三:这里为什么使用 call() 方法?

回答:这里的 call 方法是为了在使用 Object 原型上的 toString() 方法的前提下(也就是不重写 toString)改变其方法的调用者,从而得到调用者对应的类型。

5.总结

JavaScript 中常见的类型判断方式主要包括 typeofinstanceofconstructor 以及 Object.prototype.toString.call()

  • typeof 适合判断基本数据类型,但无法区分 null 和数组;

  • instanceof 通过原型链判断类型,只适用于引用类型

  • constructor 可以判断类型并访问构造函数,但在原型被重写时不可靠;

  • Object.prototype.toString.call() 直接读取引擎内部的类型标签,不依赖原型链,也不受重写影响,是最全面、最可靠的类型判断方案。

因此,在需要进行严谨类型判断的场景下,应优先使用
Object.prototype.toString.call()

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐