likes
comments
collection
share

「前端每日一问(11)」JS 如何精准地判断数据类型?

作者站长头像
站长
· 阅读数 63

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},是一个包装类,把基本类型用它们相应的引用类型包装起来,使其具有对象的性质

「前端每日一问(11)」JS 如何精准地判断数据类型?

封装一个精准判断类型的工具函数

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 有什么区别?

下一篇:

「前端每日一问(12)」JavaScript 中数组常用方法有哪些?

转载自:https://juejin.cn/post/7071835861213528078
评论
请登录