「前端每日一问(11)」JS 如何精准地判断数据类型?
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
本题难度:⭐ ⭐
难度评级最高五星,最低一星。
答:
使用 Object.prototype.toString
方法,可以精准地判断数据类型。
typeof 和 instanceof 的弊端
typeof
可以判断除了null
以外的基础数据类型,但是判断引用类型时,除了function
类型,其他的无法准确判断。instanceof
可以准确地判断各种引用类型,但是不能正确判断原始数据类型。
Object.prototype.toString
调用该方法,统一返回格式 [object Xxx]
的字符串,用来表示该对象。
// 直接调用
Object.prototype.toString({}) // '[object Object]'
// 加上 call
// 引用类型
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call(function(){}) // "[object Function]'
Object.prototype.toString.call(/123/g) // '[object RegExp]'
Object.prototype.toString.call(new Date()) // '[object Date]'
Object.prototype.toString.call(new Error()) // '[object Error]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call(new Map()) // '[object Map]'
Object.prototype.toString.call(new Set()) // '[object Set]'
Object.prototype.toString.call(new WeakMap()) // '[object WeakMap]'
Object.prototype.toString.call(new WeakSet()) // '[object WeakSet]'
Object.prototype.toString.call(document) // '[object HTMLDocument]'
Object.prototype.toString.call(window) // '[object Window]'
Object.prototype.toString.call(this) // '[object Window]'
// 原始类型
Object.prototype.toString.call(1) // '[object Number]'
Object.prototype.toString.call('1') // '[object String]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(1n) // '[object BigInt]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(Symbol('a')) // '[object Symbol]'
为什么要调用 call
call
是函数的方法,用来改变 this
指向,用 apply
也可以。
如果不改变this
指向为我们的目标变量,this
将永远指向调用的Object.prototype
。
Object.prototype.toString([]) // '[object Object]' this 指向 Object.prototype,判断类型为 Object。
Object.prototype.toString.call([]) // '[object Array]' this 指向 [],判断类型为 Array
// 重写 Object.prototype.toString 方法,把 this 打印出来看一下
Object.prototype.toString = function () {
console.log(this)
}
// 引用类型
Object.prototype.toString([]) // Object.prototype
Object.prototype.toString.call([]) // []
// 原始类型
Object.prototype.toString(1) // Object.prototype
Object.prototype.toString.call(1) // Number {1}
// 这里的 Number {1},是一个包装类,把基本类型用它们相应的引用类型包装起来,使其具有对象的性质
封装一个精准判断类型的工具函数
Object.prototype.toString 判断类型的缺陷
- 判断原始类型时,会进行
装箱操作
,产生很多临时对象
虽然只用 Object.prototype.toString
也可以判断所有的类型,但我们也可以结合 typeof
,各取所长,封装一个精准判断类型的工具函数。
function getType (obj) {
const type = typeof obj
if (type !== 'object') { // 先进行typeof判断,如果是基础数据类型,直接返回
return type
}
// 如果是引用类型,再进行如下的判断,正则返回结果
return Object.prototype.toString
.call(obj)
.replace(/^\[object (\S+)\]$/, '$1')
.toLocaleLowerCase()
}
getType(true) // boolean
getType(1) // number
getType('1') // string
getType(1n) // bigint
getType(null) // null
getType(undefined) // undefined
getType(Symbol('a')) // symbol
getType([]) // array
getType({}) // object
getType(function() {}) // function
getType(new Date()) // date
getType(/abc/) // regexp
getType(new Error()) // error
getType(document) // htmldocument
getType(window) // window
值得注意的是,调用了 toLocaleLowerCase()
,统一变成小写。
因为 Object.prototype.toString
返回的类型字符串格式不是统一的,有些是首字母大写,有些是帕斯卡形式,单词中间也有大写字母,不好记。
这个工具函数超级有用,有了它,再也不用去业务代码里写冗长的判断类型的代码了。
结尾
如果我的文章对你有帮助,你的👍就是对我的最大支持^_^
我是阿林,输出洞见技术,再会!
上一篇:
「前端每日一问(10)」typeof 与 instanceof 有什么区别?
下一篇:
转载自:https://juejin.cn/post/7071835861213528078