函数typeof、instanceof 、Object.prototype.toString 的类型判断区别

360 阅读3分钟

前言

通常在项目当中,正确判断数据类型是非常重要的,尤其是在处理异步数据、API响应、用户输入和其他动态生成的内容时。JavaScript是一种动态类型的语言,这意味着你可以在运行时自由地改变变量的类型。然而,这也可能导致一些常见的错误,比如类型不匹配导致的运行时错误,所以在运行前有一个正确判断类型的函数,对于开发者来说都是很有必要的。那么下面我们就开始介绍一些用于js类型判断的函数。

使用 typeof

  • typeof 运算符可以检查基本数据类型, 如 numberstringbooleanundefinedsymbolbigint 以及一个复杂类型function

  • 它对 null 和复杂类型(如对象、数组)的判断不够精确,因为它们都会返回 "object"

    console.log(typeof 1); // "number"
    console.log(typeof ""); // "string"
    console.log(typeof true); // "boolean"
    console.log(typeof undefined); // "undefined"
    console.log(typeof Symbol('sym')); // "symbol"
    console.log(typeof BigInt(123)); // "bigint"
    console.log(typeof function(){}); // "function"
    console.log(typeof {}); // "object"
    console.log(typeof []); // "object"
    console.log(typeof null); // "object"
    

    对于上面的结果进行总结:typeof()可以判断除null之外的原始类型,无法判断除function之外的其他引用类型。

使用 instanceof

  • instanceof 运算符用于判断一个对象是否属于某个构造函数的实例。

  • 它主要用于复合类型,如 ArrayDateRegExp 等。

  let str = 'hello'
  let num = 123
  let flag = false
  let un =undefined
  let nu = null

  let obj = {}
  let arr = []
  let fn = function () {}
  let date = new Date()

  console.log(str instanceof String)  // false
  console.log(num instanceof Number)  // false
  console.log(flag instanceof Boolean)  // false
  
  // console.log(un instanceof undefined)
  // console.log(nu instanceof null)
  // instanceof 只能判断 引用类型数据
  
  console.log(obj instanceof Object)  // true
  console.log(arr instanceof Array)   // true
  console.log(fn instanceof Function)   // true
  console.log(date instanceof Date)   // true

这里的 undefined 不能写成 Undefined,因为没有这样的基本数据类型,也没有大写 Null 的类型,而 instanceof 后面的数据类型必须首字母大写,否则会报错。

image.png

当我们将引用类型都换为如下所示的类型判断时,可以看到所有的引用类型都是对象,他们都返回true。

```
console.log(obj instanceof Object)  // true
console.log(arr instanceof Object)   // true
console.log(fn instanceof Object)   // true
console.log(date instanceof Object)   // true
```

这是因为 instanceof 的判断原理是通过原型链来查找的,如果你不知道原型链,那可以去看看我最近写的关于原型的文章 js的原型和原型链,你知道多少呢? - 掘金 (juejin.cn) ,会有意想不到的收获哦!

instanceof 会通过对象的原型链一直往上找,直到找到为止。

使用 Array.isArray

  • 专门用于判断是否为数组。
    console.log(Array.isArray([])); // true

使用 Object.prototype.toString.call()

对于toString()方法我们并不陌生,在很多都可以用到toString方法:

  1. 数组的toString()

作用:它是将数组中的元素用逗号的方式拼接字符串。

image.png 2. 其他的toString()

作用:直接将值修改成字符串。 image.png

image.png 3. 对象的toString()

也就是这种方法(Object.prototype.toString)可以返回一个描述对象的字符串,包含了具体的类型信息。

    console.log(Object.prototype.toString.call(1)); // "[object Number]"
    console.log(Object.prototype.toString.call("")); // "[object String]"
    console.log(Object.prototype.toString.call(true)); // "[object Boolean]"
    console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
    console.log(Object.prototype.toString.call(Symbol('sym'))); // "[object Symbol]"
    console.log(Object.prototype.toString.call(BigInt(123))); // "[object BigInt]"
    console.log(Object.prototype.toString.call(function(){})); // "[object Function]"
    console.log(Object.prototype.toString.call({})); // "[object Object]"
    console.log(Object.prototype.toString.call([])); // "[object Array]"
    console.log(Object.prototype.toString.call(null)); // "[object Null]"

通过阅读官方文档,找到了对象的toString实现原理,如下所示:

  • Object.prototype.toString()
  1. 如果toString接受的值是 undefined,则返回"[[object Undefined]]"。
  2. 如果 toString 接受的值是null ,则返回"[object Null]"
  3. 调用 ToObject(X) 将X转为对象,此时得到的对象 内部一定拥有一个属性[[class]],而该属性[[class]]的值就是 X 的类型
  4. 设,class是[[class]]的值
  5. 返回由"[object " 和 class 和"]" 拼接得到字符串

总结:

在实际应用中,通常结合使用这些方法以达到更准确的类型检测。例如,你可以先用 typeof 做初步判断,然后用 instanceofArray.isArray 进行更详细的类型验证。如果需要最准确的结果,Object.prototype.toString.call() 通常是最佳选择。

  • 判断原始数据类型可以用 typeof (除了null类型都可以判断)再加一个function类型
  • 判断引用类型可以用 instanceof
  • 建议还是直接用 Object.prototype.toString.call() ,然后再套上一个字符串切割函数就可以精准的判断数据类型了。