typeof、instanceof 都不靠谱?这才是 JS 类型判断的正确姿势

87 阅读3分钟

前言

今天我们来学习一个新的知识点。
JS的类型判断

类型

众所周知,类型分为两种:原始类型和引用类型,而它们中比较常用的如下:

  1. 原始类型:String,Number,Boolean,Null, Undefined, Bigint, Symbol
  2. 引用类型: Array, function, Object, Date

我们来定义一些变量

let s = 'hello'
let num = 123
let f = true
let u = undefined
let n = null
let sy = Symbol(1)
let big = 12343242n

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

有没有什么方法可以直接输出这些变量的类型呢?有的,兄弟有的

1. typeof

JavaScript 中的 typeof 是一个一元运算符,用来返回一个值的类型字符串。

基本语法:

typeof operand
// 或
typeof(operand)

typeof需要注意的点以及其工作原理如下:

  1. 可以准确的判断除了 null 之外的所有的原始类型
  2. 所有的引用类型在 typeof 眼里都是 object,除了函数

typeof 是通过将值转为二进制,来判断类型的,二进制前三位是 0 的统一被认为是引用类型,在计算机中,所有的引用类型被转为二进制前三维都是 0(除了函数),而 null 转为二进制是一整串 0

所以typeof不是万能的,是有局限的,我们需要一个更加强有力的方法来判断引用类型的类型

2. instanceof

instanceof 是 JavaScript 中用于检测对象的原型链上是否存在某个构造函数的 prototype 属性的运算符。

  1. 只能判断引用类型,无法判断原始类型
  2. 它是通过隐式原型链来查找 x 是否隶属于 X 这个类型

我们来举个例子,假设我们敲这么一段代码

console.log(arr instanceof Array);

它的输出结果是: image.png
那如果我们这样写呢:

console.log(arr instanceof Object);

你的第一反应可能是 False,但实际上,它仍然是 屏幕截图 2026-06-01 234533.png
这里就涉及到它的工作原理了:根据我们前面说的,instanceof是通过隐式原型链来查找 x 是否隶属于 X 这个类型,也就是说,它需要先判断

if(arr.__proto__ === Array.prototype)

所以第一个结果是true,而又因为

arr.__proto__.__proto__ === Object.prototype

所以arr instanceof Object 也是 true

也许你会问,主播主播,有没有什么版本强势的方法,无论是原始类型还是引用类型都能一网打尽呢?

3.Object.prototype.toString(x)

这是官方文档中的

image.png
考虑到有些兄弟可能还在挣扎过四六级,所以主播贴心地为大家翻译好了:

  1. 如果 this 值为 undefined,则返回 "[object Undefined]"。

  2. 如果此值为 null,则返回 "[object Null]"。

  3. 令 O 为调用 ToObject 并将 this 值作为参数传递所得到的结果。

  4. 令class为O的[[Class]]内部属性的值。 // const class = O.[[class]]

  5. 返回将三个字符串 "[object "、class 和 "]" 拼接后得到的字符串值。

我们平时使用的话是用这个Object.prototype.toString.call()

Object.prototype.toString = function() {
const O = ToObject(this)    
const class = O.[[class]]   
return "[object " + class + "]"  
 }

如果我们不加这个call来改变this的指向的话,this指向的就会是Object.prototype,我们加了call的话,我们假设输入123,console.log(Object.prototype.toString.call(123))

Object.prototype.toString = function() {
const O = ToObject(this)    // this == new Number(123)
const class = O.[[calss]]   // { [[calss]]: Number }
return "[object " + calss + "]"   // '[object Number]'
 }

image.png
我们再将这个输出美化一下

console.log(Object.prototype.toString.call(123).slice(8, -1));

输出结果就能直接显示Number

4.Array.isArray()

Array.isArray()是Array自身具有的方法,可以用来判断是否为数组,但由于这个方法不在Array.prototype上,所以实例对象是用不了这个方法的,只能由其自身使用。

尾声

JS类型判断就介绍到这里,咱们下期再见~