JavaScript自定义typeOf类型检查函数工作原理解析
自定义
typeOf类型检查函数原理解析 这段是JS生态里非常通用的精准类型判断方案,专门用来弥补原生typeof的判断缺陷,逐段拆解逻辑如下:
逐段执行逻辑拆解
完整函数定义如下:
const typeOf = value => Object.prototype.toString.call(value).slice(8,-1)
整个函数为链式调用,共分三步执行:
- 第一步:取未被重写的原生
Object.prototype.toString方法
所有JS内置类型的原型链最终都会指向Object,Object原型上自带的toString方法没有被任何子类重写,它的固定规则是:当方法内部的this指向某个值时,会返回格式为[object 类型名]的字符串,其中「类型名」是JS引擎内部存储的真实类型标签,不会受值本身的自定义方法影响。
不能直接写value.toString()的原因是:数组、函数、日期等绝大多数内置类型都重写了自己的toString方法,比如数组调用toString会返回逗号拼接的元素字符串,函数调用toString会返回函数源码字符串,根本拿不到类型信息。 - 第二步:通过
.call(value)绑定this到待检测值call是函数原型上的方法,可以强行修改函数执行时的this指向。这里把原始toString方法的this从Object原型实例,改成传入的待检测值value,不管传入的是原始类型(数字、字符串、布尔、null、undefined、Symbol、BigInt)还是引用类型(数组、对象、函数、日期、正则等),JS引擎都能正确识别它的内部标签,返回对应格式的字符串。
常见输入在这一步的返回结果:- 传入数字
1:返回"[object Number]" - 传入字符串
"a":返回"[object String]" - 传入数组
[1]:返回"[object Array]" - 传入箭头函数
()=>{}:返回"[object Function]" - 传入
null:返回"[object Null]" - 传入普通对象
{}:返回"[object Object]"
- 传入数字
- 第三步:通过
.slice(8, -1)截取纯类型名
上一步返回的字符串里,前8个字符是固定前缀[object(逐字符计数:[、o、b、j、e、c、t、空格,刚好8个字符),最后1个字符是固定后缀]。slice(8, -1)的规则是:从字符串索引为8的位置开始截取,一直截到倒数第一个字符之前(参数-1代表倒数第一个位置,作为结束索引时不包含该位置字符),刚好把前后固定的包裹字符去掉,拿到纯类型字符串。比如"[object Array]"经过截取后就得到"Array"。注:你示例里标注的返回值是全小写的
number/string属于笔误,原函数实际返回首字母大写的类型名,如果需要全小写结果,在slice后面链式调用.toLowerCase()即可。
该方案对比原生typeof的优势
原生typeof是操作符而非函数,存在很多历史遗留的判断bug:
- 对
null做判断会错误返回"object" - 对数组、日期、正则、Map、Set等引用类型做判断,统一返回
"object",无法区分具体类型
这个自定义方法可以准确识别所有JS内置类型,是目前兼容性最好、判断最准确的通用类型检查方案。
内容的提问来源于stack exchange,提问作者poppy
相关产品推荐
相关产品推荐

