数据类型检测方法与区别

简介

typeof 一般是用来判断变量是否存在,返回他的类型,其中基本数据类型 null 返回的是一个 object,但 null 不属于引用数据类型,typeof 除了判断 function 函数会识别,其他的引用类型输出为 object
instanceof 一般是用来判断引用数据类型,但不能正确判断基本数据类型,根据在原型链中查找判断当前数据的原型对象是否存在返回布尔类型
constructor既可判断基础类型又能判断引用类型但不能判断null和 undefined,判断原理和instanceof 相似
Object.prototype.toString3 种方法各有各的优缺点,一般我们推荐此方法判断数据类型 ,返回统一的格式object Xxx

一、typeof

typeof 操作符返回一个字符串,表示未经计算的操作数的类型

语法

csharp 复制代码
typeof operand
typeof operand

operand表示对象或原始值的表达式,其类型将被返回

示例

javascript 复制代码
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof console // 'object'
typeof console.log // 'function'

可以看出前typeof可以清楚的分辨 6 种基础数据类型。虽然typeof nullobject,底层原理是所有数据类型都会被以二进制的形式储存,typeof通过判断二进制来分别数据类型,而nullobject的二进制转换都为000,但不代表null就是引用数据类型,并且null本身也不是对象

所以,nulltypeof之后返回的是有问题的结果,不能作为判断null的方法。如果你需要在 if 语句中判断是否为 null,直接通过===null来判断就好

同时,可以发现引用类型数据,用typeof来判断的话,除了function会被识别出来之外,其余的都输出object

如果我们想要判断一个变量是否存在,可以使用typeof:(不能使用if(a), 若a未声明,则报错)

csharp 复制代码
if (typeof a != 'undefined') {
  //变量存在
}

二、instanceof

instanceof 运算符的原理是利用构造函数的 prototype 属性是否出现在某个实例对象的原型链上

语法

kotlin 复制代码
object instanceof constructor

object为实例对象,constructor为构造函数

构造函数通过new可以实例对象,instanceof能判断这个对象是否是之前那个构造函数生成的对象

示例

javascript 复制代码
// 定义构建函数
let Car = function () {}
let benz = new Car()
benz instanceof Car // true
let car = new String('xxx')
car instanceof String // true
let str = 'xxx'
str instanceof String // false

关于instanceof的实现原理,可以参考下面:

javascript 复制代码
function myInstanceof(left, right) {
  // 这里先用typeof来判断基础数据类型,如果是,直接返回false
  if (typeof left !== 'object' || left === null) return false
  // getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
  let proto = Object.getPrototypeOf(left)
  while (true) {
    if (proto === null) return false
    if (proto === right.prototype) return true //找到相同原型对象,返回true
    proto = Object.getPrototypeof(proto)
  }
}

也就是顺着原型链去找,直到找到相同的原型对象,返回true,否则为false

区别

typeofinstanceof都是判断数据类型的方法,区别如下:

  • typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值
  • instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型
  • typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断

可以看到,上述两种方法都有弊端,并不能满足所有场景的需求

三、constructor

constructor判断类型的方式和instanceof相似,每个构造函数都会有一个原型对象,而原型对象上又有一个constructor属性指向原型对象的构造函数,同时构造函数的实例对象有个__proto__属性指向原型对象,听起来有点乱,下面一张图来说明

js 复制代码
   function Car() {} 
   const instance = new Car()
   instance .constructor === Car // true
   ({}).constructor === Object //true

不同于instanceof方法,constructor既可以判断引用数据类型,也可以判断基础数据类型,因为基础数据类型本质上也 Number, Boolean等构造函数的实例对象

js 复制代码
   (1234).constructor === Number // true
   (true).constructor === Boolean // true
   ('string').constructor === String // true

constructor也有缺点,它不能检测nullundefined,因为这两者没有constructor属性

js 复制代码
  let num
  let num2 = null
  num.constructor === undefined  //Cannot read properties of undefined (reading 'constructor')
  num2.constructor === null  //Cannot read properties of null (reading 'constructor')

四、Object.prototype.toString(推荐使用)

Object.prototype.toString可以同时检测基本数据类型和引用数据类型,并且没有上述方法的缺点,调用该方法,统一返回格式"[object Xxx]"的字符串

示例

javascript 复制代码
Object.prototype.toString({}) // "[object Object]"
Object.prototype.toString.call({}) // 同上结果,加上call也ok
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(function () {}) // "[object Function]"
Object.prototype.toString.call(null) //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g) //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(document) //"[object HTMLDocument]"
Object.prototype.toString.call(window) //"[object Window]"

继续使用Object.prototype.toString.call([]).slice(8,-1).toLowerCase()可以得到具体的类型。

了解了toString的基本用法,下面就实现一个全局通用的数据类型判断方法

typescript 复制代码
function getType(obj) {
  let type = typeof obj
  if (type !== 'object') {
    // 先进行typeof判断,如果是基础数据类型,直接返回
    return type
  }
  // 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
  return Object.prototype.toString.call(obj).replace(/^[object (\S+)]$/, '$1')
}

使用如下

scss 复制代码
getType([]) // "Array" typeof []是object,因此toString返回
getType('123') // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null) // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined) // "undefined" typeof 直接返回
getType() // "undefined" typeof 直接返回
getType(function () {}) // "function" typeof能判断,因此首字母小写
getType(/123/g) //"RegExp" toString返回
相关推荐
mldong6 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排6 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60617 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角8 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!8 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰8 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi10 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen10 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马11 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu11 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss