JS数据类型判断的九种方式

news2025/1/22 17:58:52

JS 的数据类型检测是一道经典的八股文面试题。相信大家都能条件反射的回答出 4 种方法:typeof、constructor、instanceof 和 Object.prototype.toString,并且对它们各自的优缺点也是张口就来。

本文对这些方法做了简单归纳,同时又补充了其他 5 种和数据类型检测有关的方法,供诸君食用。

typeof:检测基础数据类型和函数很好用

typeof 应该是我学习到的第一个 JS 的方法,也是使用频率最高的一个用来检测数据类型的方法。

它能准确判断出的数据类型有:Number,String,Boolean,Undefined,Symbol,BigInt,Function。

它的缺点就是不能准确判断 null 的类型,而是返回 “object”。对于数组,日期,普通对象等数据,统一返回 “object”。

所以在判断基本数据类型(除了 null)和函数类型时,都会使用它。

constructor:返回实例对象的构造函数

学习 JS 到面向对象的阶段时,会学到 JS 的原型链和原型对象,会学到通过 new 一个构造函数,来创建实例对象。

构造函数的原型对象上会有一个 constructor 属性,指向了构造函数自身,所以实例对象通过原型链访问 constructor 属性,就能找到自己的构造函数,也就是自己的类型了。

它的本意是用来标识自己的构造函数,却临时拉来当壮丁,用来判断数据类型,当然也存在一定的风险:

  • null,undefined 没有构造函数,自然也就访问不到该属性,因此不能使用此属性来判断
  • constructor 可以被改写,所以不一定准确

来看几个例子:

console.log((1).constructor === Number) // true
​
console.log([1, 2, 3].constructor === Array) // true
​
console.log(undefined.constructor === Array) // 报错 

在平时写代码时,基本上不会用它来做数据类型的检测。

instanceof:沿着原型链去找

它和 constructor 一样,也是临时拉来当壮丁。它的作用是检测实例对象是不是属于某个构造函数,可以用来做数据类型的检测。

术业有专攻,所以它也有缺点:

  • 不能检测基本数据类型

  • 原型链可能被修改,导致检测结果不准确

  • 只要能在原型链上找到构造函数,就返回 true,所以类型可能不准确

来看几个例子:

console.log(1 instanceof Number) // false
​
console.log([] instanceof Array) // true
​
console.log([] instanceof Object) // true 

实际中 instanceof 也很少用。

Object.prototype.toString:是个大拿

看名字它是用来将一个值转为字符串的,但其实并不是,它是一个专门检测数据类型的方法。

它返回的值是一个形如 [object Object] 的字符串,比如:

console.log(toString.call('123'))        // [object String]
console.log(toString.call(null))         // [object Null]
console.log(toString.call(true))         // [object Boolean]
console.log(toString.call({}))           // [object Object]
console.log(toString.call([]))           // [object Array]
console.log(toString.call(function(){})) // [object Function]
console.log(toString.call(new Map))      // [object Map]
console.log(toString.call(new WeakSet))  // [object WeakSet] 

通常会编写一个函数,对返回的字符串从第8位做一个截取,截取到倒数第一位,再去做类型比较。

Symbol.toStringTag:自定义类型

上面的 Object.prototype.toString 方法,之所以对不同的数据类型,返回不同的标识字符串,就是因为 Symbol.toStringTag

Symbol.toStringTag 是一个内置符号属性,它的值是一个字符串,用于表示一个对象的默认描述,也就是调用 Object.prototype.toString 会返回的内容,比如:

let obj = {}
obj[Symbol.toStringTag] = 'ABC'
console.log(Object.prototype.toString.call(obj)) // [object ABC] 

对于自定义对象,调用上面的方法,都只会返回 [object Object]。此时就可以使用 Symbol.toStringTag 来指定一个确定的类型了,比如:

class Person{
    get[Symbol.toStringTag](){
        return 'Person'
  }
}
let person = new Person()
​
console.log(Object.prototype.toString.call(person)) // [object Person] 

Object.prototype.isPrototypeOf:和 instanceof 类似

isPrototypeOf 和 instanceof 类似,都是基于原型链和原型对象去做判断的。它用来检查一个对象是否存在于另一个对象的原型链上。

function Person() {
    
}
​
let person = new Person()
​
console.log(Person.prototype.isPrototypeOf(person)) 

Array.isArray:专业检测数组三十年

起初以为它是 ES6 提供的新方法,后来得知其实属于 ES 5.1 规范。

看名字就知道,它是专门用于检测数组类型的,该方法的命名真实言简意赅。

Array.isArray([]) // true 

Number.isNaN

这个方法就是真的属于 ES6 标准了。

我们知道,JS 中有一个特殊的“数字” NaN,表示 not a number,不是一个数字,但它却归属于数字类型:

console.log(typeof NaN) // 'number' 

NaN 用于表示不是一个数字,它不等于任何值,包括它本身。在 ES6 之前,windows 对象提供了一个全局方法 isNaN,用于判断一个数字是不是 NaN:

isNaN(10) // false
isNaN('abc') // true
isNaN(NaN) // true 

可以发现,isNaN 对于字符串的检测结果也是 NaN。但这其实并不严谨,它对要判断的数据做了一个隐式类型转换,先转为数字再进行判断。而NaN 的检测应该仅限于数字类型,所以 ES6 提供了 Number.isNaN 方法:

Number.isNaN(NaN) // true
Number.isNaN('123') // false 

它能判断一个值是否严格等于NaN。

等比较:与固定值进行比较

直接通过与一个特定的值进行比较,从而判断数据的类型,比如:

let value = null
console.log(value === null) // true
​
// 同时判断一个值是 undefined 或者 null
let value
console.log(value == null) // true 

总结

本文整理了 JS 中常用的判断数据类型的方法,其中 typeof 和 Object.prototype.toString 使用场景是最多的,对一些特殊的数据类型,比如 null,NaN,自定义类型,可以选择其他的方式去进行判断,做到灵活运用。

关于数据类型的检测, 如果你还有其他的方式,欢迎评论补充,一起学习。

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode:112. 路径总和、113. 路径总和 II(C++)

目录 112. 路径总和: 问题描述: 实现代码与解析: 递归: 原理思路: 迭代: 原理思路: 113. 路径总和 II: 问题描述: 实现代码与解析: 迭代&#xff…

分享66个NET源码,总有一款适合您

NET源码 分享66个NET源码,总有一款适合您 NET源码下载链接:https://pan.baidu.com/s/1-H0UV3yly3p1PXbeLAvMtA?pwdk06f 提取码:k06f page_count 1 # 每个栏目开始业务content"text/html; charsetgb2312"base_url "http…

go defer return panic 执行顺序

根据代码实例运行结果来总结说明:定义一个函数,有多个defer (用于判断多个defer执行顺序),有panic和 return (判断与defer对比执行顺序)一、函数中有panicpackage mainimport "fmt"fu…

【矩阵论】8. 常用矩阵总结——秩1矩阵,优阵(单位正交阵),Hermite阵

矩阵论 1. 准备知识——复数域上矩阵,Hermite变换) 1.准备知识——复数域上的内积域正交阵 1.准备知识——Hermite阵,二次型,矩阵合同,正定阵,幂0阵,幂等阵,矩阵的秩 2. 矩阵分解——SVD准备知识——奇异值…

【性能调优】【离线任务】flink处理离线任务(8000个小文件?200多亿数据量?)稳定性与性能调优探索

文章目录一、场景描述1. 任务类型描述2. 问题任务二、相关理论1.Task Slots and Resources1.1. slots与资源的隔离和共享1.2 建议cpu和slot数关系2. tm的资源配置是否合适2.1. flink load problems2.2. 阿里 flink资源配置建议三、问题分析与解决1. 测试结果比对1.1. 任务11.2.…

小程序学习(2)-----常用的各类组件

新建项目 项目->新建项目-小程序,如下图所示 新建小程序页面 只需要在 app.json->pages 中新增页面的存放路径,小程序开发者工具可帮我们自动创建对应的页面文件,如图所示: 2.常用的视图容器类组件 ① view 普通视图区域类…

Java基础算法每日5道详解(3)

136. Single Number 单号 Given a non-empty array of integers nums, every element appears twice except for one. Find that single one. You must implement a solution with a linear runtime complexity and use only constant extra space. 给定一个非空整数数组 nu…

在Multisim导入TI提供的SPICE模型

对在multisim中导入TI模型的一个记录。 multisim中只有常规的元器件,对于很多元器件multisim都没有相应的模型,这就需要手动导入了。 Multisim导入模型1、从官网下载相应的模型文件2、在Multisim中导入模型3、写在后面1、从官网下载相应的模型文件 &…

c/c++ 函数(一) setw()、isdigit()、isalpha()、atoi()、itoa()

目录 1、setw(int n) <iomanip> 2、int isdigit(char ch) <ctype.h> 3、int isalpha(int c) <ctype.h> 4、int atoi(const char* str) <stdlib.h> 5、char* itoa(int num) <stdlib.h> 1、se…

Linux 基本权限

目录 1 shell命令以及运行原理 1.1 理解 1.2 意义 2 Linux权限的概念 2.1 概念 2.2 用户分类 2.3 Linux文件属性 2.4 Linux文件权限 2.4.1 文件访问者的分类&#xff08;人&#xff09; 2.4.2 root&&普通用户 vs 拥有者&&所属组&&other 2.4…

异步架构,避免相互依赖的系统耦合

前言&#xff1a; 使用缓存架构可以减少不必要的计算&#xff0c;快速响应用户请求&#xff0c;但是缓存只能改善系统的读操作性能&#xff0c;也就是在读取数据的时候&#xff0c;可以不从数据源中读取&#xff0c;而是通过缓存读取&#xff0c;以加速数据的读取速度。 但是…

vulnhub DC系列 DC-6

总结:wpscan爆破&#xff0c;nmap提权 下载地址 DC-6.zip (Size: 619 MB)Download: http://www.five86.com/downloads/DC-6.zipDownload (Mirror): https://download.vulnhub.com/dc/DC-6.zip使用方法:解压后&#xff0c;使用vm直接打开ova文件。 漏洞分析 信息收集 这里还是使…

4. 数据处理:用R语言实现【多路替换】真高效!!

b站课程视频链接&#xff1a; https://www.bilibili.com/video/BV19x411X7C6?p1 腾讯课堂(最新&#xff0c;但是要花钱&#xff0c;我花99&#x1f622;&#x1f622;元买了&#xff0c;感觉讲的没问题&#xff0c;就是知识点结构有点乱&#xff09;&#xff1a;https://ke.qq…

Linux中的vim最小集、指令集及其配置

目录 1. vim 最小集 2 vim指令集 2.1 命令模式的指令 2.1.1 插入模式 2.1.2 移动光标 2.1.3 删除文字 2.1.4 复制 2.1.5 替换 2.1.6 撤销 2.1.7 更改 2.1.8 跳至指定的行 2.1.9 shift ~:快速大小写切换 2.2 末行模式的指令 2.2.1 set nu/set nonu 2.2.2 vs file…

【自学Python】Python变量

Python变量 Python变量教程 不论是使用哪种高级程序语言编写程序&#xff0c;变量都是其程序的基本组成单位。变量相当于内存中一个数据存储空间的表示&#xff0c;通过变量名可以访问到变量的具体的值。 Python变量 Python 是弱类型语言&#xff0c;因此 Python 变量无须声…

Hudi的核心概念 —— 时间轴(TimeLine)

文章目录时间轴&#xff08;TimeLine&#xff09;时间轴&#xff08;TimeLine&#xff09; 就是一个时间线&#xff0c;它的每一个操作都记录在内&#xff0c;每一个时刻&#xff0c;你做了什么事情&#xff0c;对某一个时刻&#xff0c;记录一个时刻的数据 Hudi 的核心是维护…

擎创运维大数据治理解决方案,荣膺金融业数字化转型突出贡献奖

近日&#xff0c;由《金融电子化》杂志社主办的“2022中国金融科技年会暨第十三届金融科技应用创新奖颁奖典礼”成功于线上举办。擎创科技“运维大数据治理解决方案”&#xff0c;荣膺“2022科技赋能金融业数字化转型突出贡献奖”。人民银行《金融科技发展规划&#xff08;2022…

C++ string类

在c语言中&#xff0c;我们想要记录字符串需要创建一个字符串的数组&#xff0c;而c则提供了另一种方式&#xff1b; 也就是这篇博客所说的string类&#xff1b; string类 #include<string> 作为字符串数组的升级版&#xff0c;string类自然也有它的独特之处——可变长数…

自动驾驶标定基础知识

目录基础概念1. 缩略语2. 为什么需要外参标定3. 基于使用场景的标定分类4. 基于方法的分类5. 基础坐标系6. 超差EOL标定1.EOL特点2. EOL标定流程3. EOL标定软件约束4. EOL标定软件流程5. 算法设计原则6. 算法基本原理背景式标定1.背景式标定的特点2. 背景式标定运行流程3. 背景…

高级树结构之线索化二叉树

文章目录一 线索化二叉树简介二 线索化规则三 前序线索化3.1 代码演示四 中序线索化4.1 代码演示五 后序线索化5.1 代码演示一 线索化二叉树简介 线索化&#xff1a;将一颗二叉树的结点指向为空的指针&#xff0c;线索化为某一种顺序遍历的的指向下一个按顺序的结点的指针一颗…