前言
刚入门 JS 的同学,几乎全都栽在数据类型判断上:想用typeof分辨数组却返回 object,拿instanceof判断基础类型频频翻车,碰到 null、正则、日期更是判断错乱。明明三个判断方法都学过,什么时候用哪个始终分不清,项目里类型校验反复踩坑。本文抛开生硬定义,口语化拆解三种 API 底层逻辑,逐个梳理适用范围、优缺点与易错场景,从原始值、引用对象到特殊内置类型全覆盖。看完不用死记用法,开发时精准选型,一次性搞定 JS 全类型精准判断。
JS类型
- 原始类型:string,number,boolaen,null, undefined, bigint, Symbol
- 引用类型: Array, function, object, Date
这些都在往期文章五分钟带你了解js中各种数据类型,让初学者也能轻松记忆前言 在JavaScript的世界里,数据类型是构建一切应用的基石 - 掘金中提到过,读者可自行选择查看。
类型判断方法
1.1 typeof
- 可以准确的判断除了 null 之外的所有的原始类型
- 所有的引用类型在 typeof 眼里都是 object,除了函数是function
接下来,我们用一段代码给你具体说明举例:
js
let a = 'hello'
let num = 123
let f = true
let d = undefined
let n = null // 返回 object
let sy = Symbol(1)
let big = 1223445326n
let arr = []// 返回 object
let obj = {} // 返回 object
let fn = function(){}
console.log(typeof fn);
console.log(typeof a);
console.log(typeof num);
console.log(typeof f);
console.log(typeof d);
console.log(typeof n);
console.log(typeof sy);
console.log(typeof big);
console.log(typeof arr);
console.log(typeof obj);
打印结果为:
我们可以看到,用typeof方法判断变量类型是直接输出其类型,对于原始类型来说,判断可以说非常准确,除了null,对于引用类型,只有function属于 JavaScript 给开发者开的 VIP,可以准确判定,数组和对象输出都是object,这就出现问题了,数组和对象根本区分不出来。那么问题来了,造成上面两种特例的原因是什么呢,这就要从js底层说起。
typeof是通过将值转为二进制,来判断类型的,二进制前三位是 0 的统一被认为是引用类型,在计算机中,所有的引用类型被转为二进制前三维都是 0(除了函数),而 null 转为二进制是一整串 0
2.2 instanceof
- 只能判断引用类型,无法判断原始类型
- 它是通过隐式原型链来查找 x 是否隶属于 X 这个类型
同样用代码展示
js
let a = 'hello'
let num = 123
let f = true
let d = undefined
let n = null // 返回 object
let sy = Symbol(1)
let big = 1223445326n
let arr = []// 返回 object
let obj = {} // 返回 object
let fn = function(){}
console.log(a instanceof String);//false
console.log(num instanceof Number);//false
console.log(f instanceof Boolean);//false
console.log(d instanceof undefined);//报错
console.log(n instanceof null);//报错
console.log(sy instanceof Symbol);//false
console.log(big instanceof BigInt);//false
console.log(arr instanceof Array);//true
console.log(obj instanceof Object);//true
console.log(fn instanceof Function);//true
运行结果:

可以看到,null和undefined由于不存在,所以判断时会报错,且只能判断引用类型,那他的原型链查找底层原理是什么呢?让我们用代码一一拆解
js
function myInstanceof(left, right){
if(typeof left !== 'object' && typeof left !== 'function' || left == null ){
return false
}
while(left !== null){
if(left.__proto__ === right.prototype){
return true
}
left = left.__proto__
}
return false
}
console.log(myInstanceof(function(){},Function));
1.如果左边待判断的变量不是对象、不是函数或者左边是 null /undefined,直接返回 false,这就是说string/number/boolean 等原始类型直接返回false
2.判断当前对象的隐式原型 __proto__是否 等于 右边构造函数的显式原型 prototype ,相等 → 就是它的实例 → return true
3.不相等就继续往上找,直到到找到原型链终点 null 仍未匹配,return false
3.3 Object.prototype.toString.call(x)
我们先看执行效果再讨论原理,代码示例:
js
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(){}
console.log(Object.prototype.toString.call(s));
console.log(Object.prototype.toString.call(num));
console.log(Object.prototype.toString.call(arr).slice(8, -1));
console.log(Object.prototype.toString.call(fn).slice(8, -1)); // '[object Function]'

该方法无论原始类型或引用类型都能判断,输出为[object 对象类型]。而要让其输出类型字符串,则要补充:字符串slice方法:
slice方法可以实现将字符串从左端下标切割到右端下标,左闭右开,文中
slice(8, -1)指切到最左端但不包含
看到了这么强大的方法,我们不禁会想其原理,而要了解其原理,就得先;了解Object.prototype.toString(x)的原理,首先我们抛砖引玉给出官方文档:
相信你看完肯定一脸懵逼,让我来给你详细拆解:
如果 this 值为 undefined,则返回 "object Undefined"。
如果此值为 null,则返回 "object Null"。
令 O 为调用 ToObject 并将 this 值作为参数传递所得到的结果。 // const O = ToObject(this)
// O 永远都是 Object
令class为O的\[Class]内部属性的值。 // const class = O.\[calss]
返回将三个字符串 "object "、class 和 "" 拼接后得到的字符串值。
这下你懂了Object.prototype.toString(x)原理是ToObject创建一个对象o并将 this 值作为参数传递,而由隐式绑定规则,该对象中this永远指向Object的原型函数,即Object,js又默认执行const class = O.[[calss]],class即为Object,加上显示绑定call后,相当于执行:
js
Object.prototype.toString = function() {
// const O = ToObject(this) // this == new Number(123)
// const class = O.[[calss]] // { [[calss]]: Number }
// return "[object " + calss + "]"
// }
强制改变this指向创建的实例对象,从而实现类型准确判断。
补充;Array.isArray()
Array.isArray()是专门用于判断数组的方法,挂载方式为Array.isArray = function(){},不是在Array原型函数上,因此const arr = \[\] arr.isArray // 错,这样的判断是错误的。
总结
四种类型判断方式能力对比如下:
| 方法 | 原始类型 | 引用类型 | null | 数组 |
|---|---|---|---|---|
| typeof | ✅ | ❌ | ❌ | ❌ |
| instanceof | ❌ | ✅ | ❌ | ✅ |
| Object.prototype.toString | ✅ | ✅ | ✅ | ✅ |
| Array.isArray | ❌ | 仅数组 | ❌ | ✅ |
记住一句话:
javascript
typeof 看身份证
instanceof 查族谱
Array.isArray 查户口本
Object.prototype.toString 看出生证明
当你不知道该用什么的时候:
Object.prototype.toString 永远是最稳妥的选择。