JavaScript 数据类型判断

news2024/11/24 8:35:20
(生活的道路一旦选定,就要勇敢地走到底,决不回头。——左拉)

在这里插入图片描述

typeof

typeof是在javascript编码过程中最常用的判断数据类型的方法,常用来判断数字,字符串,布尔值和undefind

console.log(typeof 1); // number
console.log(typeof ''); // string
console.log(typeof true); // boolean
console.log(typeof false); // boolean
console.log(typeof undefined); //undefined

但不能用来判断复杂数据类型,比如以下案例

console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof null); // object

这是因为javascript中的数据类型为两大类,原始值和对象值,其实也就是基础类型和引用类型。
基础类型有undefined,null,boolean,number,string
引用类型有array,object,date,regexp,function等。
每当使用typeof时,v8引擎会判断该数型的类型,如果是基础类型,则返回对应的类型字符串,如果是引用类型,则统一返回object。
需要注意的是typeof null也会返回object,这是js早期的bug一直没解决,正常情况下null就是null。
关于 typoef null等于object的说明
日常判断基本类型使用typeof的话,问题不大。但假如要判断某一个属性的类型是否是数组就做不到了,因为对于typeof来说,数组和对象都是object。并且在一些复杂的业务场景中,还要对类与类之间进行判断,比如A类是否属于B类等自定义对象的类型检查场景,typeof就更无法满足了。

instanceof

为了解决typeof上述中无法解决的业务场景,js还提供了instanceof来通过原型链和原型的比较来达到类型检查的目的。

console.log([] instanceof Array); // true
console.log({} instanceof Object); // true
class Student { }
const student = new Student();
class Car { }
const car = new Car();
class Train extends Car { }
const train = new Train();
console.log(student instanceof Car); // false
console.log(car instanceof Car); // true
console.log(train instanceof Car); // true

其原理还要从js的原型链和原型说起

原型和原型链

如果要自己实现一个instanceof,那么就是这样

const instanceof_custom = (A, B) => {
  let L = A.__proto__;
  const R = B.prototype;
  while (true) {
    if (L === null)
      return false;

    if (R === L)  // 当 R 显式原型 严格等于  L隐式原型 时,返回true
      return true;

    L = L.__proto__;
  }
};

通过代码可以看出,通过递归查找A原型链上的原型来对比B的原型是否相等来达到类型判断的目的,一直到原型链为null时终止。
虽然这样能判断数组和对象了,但又带来了新的问题,比如以下示例

console.log([] instanceof Object); // true
console.log({} instanceof Object); // true
console.log(new Number() instanceof Object); // true
console.log(new String() instanceof Object); // true
console.log(new Boolean() instanceof Object); // true

由于数组和对象的原型链上都有object,就导致他们在用原型链和原型进行对比的时候就会出现相等的情况。

Object.prototype.toString.call

为了解决上述问题,js又提供了Object.prototype.toString()方法。
在js中每一个类型都有着自己的toStirng方法,他们各自返回自己转换成字符串之后的结果,比如

const str = '123';
const number = 123;
const fun = () => { };
const boolean = true;
const array = [1, 2, 3];
const obj = {};
const cls = class { }
console.log(str.toString()); // '123'
console.log(number.toString()); // '123'
console.log(fun.toString()); // '() => { }'
console.log(boolean.toString()); // 'true'
console.log(array.toString()); // '1,2,3'
console.log(obj.toString()); // '[object Object]'
console.log(cls.toString()); // 'class { }'

Object.prototype.toString()能够返回"[object Type]",其中Type是对象类型。如果对象具有Symbol.toStringTag值为字符串的属性,则该值将用作Type. 许多内置对象(包括Map和Symbol)都有一个Symbol.toStringTag. 一些早于 ES6 的对象没有Symbol.toStringTag,但仍然有一个特殊的标签,他们的值与他们的类型相同,包含Array,Function,Error,Boolean,Number,String,Date,RegExp。
而如果我们给他们自定义Symbol.toStringTag属性的话,就业能够达到自定义标签的目的。

class ValidatorClass {
  get [Symbol.toStringTag]() {
    return 'Validator';
  }
}

Object.prototype.toString.call(new ValidatorClass()); // "[object Validator]"

在这里我们先我们删除Array自身的toString方法,然后让它通过原型链来使用上层Object的toString方法来测试一下。

const array = [1, 2, 3];
console.log(array.toString()); // ‘1,2,3’
delete Array.prototype.toString;
console.log(array.toString()); // ‘[object Array]’

至此,解决了instanceof判断对象的问题,但我们在实际应用中最好不要删除原型方法,这样会给程序造成极大的隐患。
那么就可以用js中的call方法来改变this指向,替换Object内部属性值的目的。让Object的toString方法读取Array的特殊标签,那么就可以返回‘[object Array]’了

结论

综上所述,三种判断js类型的方法各有所长,typeof写法简单便于理解,instanceof善于判断自定义对象,Object.prototype.toString.call虽然写起来稍复杂,但除了自定义对象,其他的类型都可以进行判断
至于只用哪一种,还要结合业务场景来进行选择。

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

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

相关文章

ROS Noetic版本 rosdep找不到命令 不能使用的解决方法

使用rosdep指令来安装开源包所需的依赖是很方便的,本文主要介绍ROS Noetic版本中使用rosdep,报错找不到命令 ,rosdep不能使用的解决方法。 rosdep:找不到命令 Command rosdep not found, but can be installed with:sudo apt ins…

怎么取消parallels更新,关闭Parallels Desktop 更新提示

自动更新问题 使用Parallels Desktop一段时间后,会主动提示更新,MacOS上最好的虚拟机:Parallels Desktop,但在使用过程中每次启动都要检查更新,比较烦人 如图: 解决方法 取消parallels更新 点击Parall…

v4l2框架

v4l2框架 文章目录 v4l2框架框架1.硬件相关层uvc_probeuvc_register_chainsuvc_register_termsuvc_register_video 2.核心层__video_register_device 3.虚拟视频驱动vivid分析入口vivid_init注册vivid平台驱动vivid_probevivid_create_instance 框架 1.硬件相关层 driver/medi…

2023 hnust 大三下 嵌入式 期中考试复习笔记

前言 ★:重点※:补充内容❓:还没搞懂的内容主要来源:教材、PPT、百度百科、AI重点来源:4-6班感谢:lyf总结得很草率,因为没听过课,也玩不懂 重点汇总 考试题型 选择(40…

C#_Struct与Class的差异

简述 struct属于值类型,class属于引用类型 存储地址 struct储存于栈,class储存于堆(class于栈中储存引用) 传参性质 struct属于值传递,在函数内对参数进行修改,不会修改struct class处于引用传递&…

day40—选择题

文章目录 1.上网的时候,访问某个网页却突然出现了某个运营商的网页(如联通、电信)。出现此问题可能的原因是(A)2.某浏览器发出的HTTP 请求报文如下,下列叙述中,错误的是(C&#xff0…

阿里云CentOS服务器安装Redis教程(一步步操作)

使用阿里云服务器ECS安装Redis数据库流程,操作系统为CentOS 7.6镜像,在CentOS上安装Redis 4.0.14,云服务器选择的是持久内存型re6p实例,新手站长分享阿里云CentOS服务器安装Redis流程方法: 目录 在CentOS系统中部署R…

【内网】面试·HVV专题

【内网】面试HVV专题 1.目标主机没有nc时如何获取反向shell2.说说你了解的隧道技术SSH隧道HTTP/HTTPS协议DNS协议1.目标主机没有nc时如何获取反向shell Python反向shell执行如下命令,在VPS上监听本地2222端口 nc -lvp 2222在目标主机上执行如下命令: bash反向shell执行如下命…

数据结构/栈实现队列

前言 在学习数据结构的过程当中,我们会学到栈和队列,在本篇文章中,重点讲解的是栈实现队列,故关于栈和队列的讲解只是简单带过。 一、栈 栈是一种后进先出的线性表,即只能在固定的一端进行插入和删除。 栈 方法 Stac…

(2)Qt的UI入门

目录 1. QWidget类(重点) 2. 子组件 1. QWidget类(重点) QWidget类是Qt中所有组件和窗口的基类,其内部规定了组件和窗口的基本规则和功能。 Qt中每个属性的文档中都有Access functions部分,表示其支持的读写…

机器学习实战教程(十二):聚类算法Kmeans

聚类概念 聚类是一种无监督的机器学习方法,它主要是通过在数据集中找到相似的样本并将它们分组来发现数据中的模式和结构。聚类算法可以将数据分成具有相似特征的组,每个组被称为一个簇。 常见的聚类算法有以下几种: K-means聚类算法&#…

python面向对象三大特性详解 - 封装 继承 多态

前言 面向对象编程有三大特性:封装、继承、多态,本文带大家来认识和了解这三个特性~ 补充 - 新式类 & 经典类 在python2.x中,新式类是继承了object类的子类,以及该子类的子类 子子类...;经典类就是没有继承没有…

java基础入门-05

Java基础入门-05 13、面向对象进阶(static&继承)1.1 如何定义类1.2 如何通过类创建对象1.3 封装1.3.1 封装的步骤1.3.2 封装的步骤实现 1.4 构造方法1.4.1 构造方法的作用1.4.2 构造方法的格式1.4.3 构造方法的应用 1.5 this关键字的作用1.5.1 this关…

MapReduce 源码分析-1

源码追踪 Class Job 作为使用Java语言编写的MapReduce城西,其入口方法位main方法,在MapReduce Main方法中,整个核心都在围绕着job类,中文称之为作业。 public class WordDriver {public static void main(String[] args) throw…

解决vue中父组件通过props向子组件传递数据,子组件接收不到

问题&#xff1a;父组件在挂载时向后端发起请求获取数据&#xff0c;然后将获取到的数据传递给子组件&#xff0c;子组件想要在挂载时获取数据&#xff0c;获取不到。 代码示例&#xff1a; //父组件 <template><div><HelloWorld :message"message"…

Mysql数据库中的用户管理与授权

1.登录用户的管理 1.1 查看用户密码的信息 用户信息存放在 mysql 数据库下的 user 表&#xff08;MySQL 服务下存在一个系统自带的 mysql 数据库&#xff09;。 经常使用的查看密码信息的命令&#xff1a; 能看到密码信息&#xff1a;是经过加密后的密码信息 select user…

真题详解(关系模型)-软件设计(六十六)

真题详解(ICMP)-软件设计&#xff08;六十五)https://blog.csdn.net/ke1ying/article/details/130475620 2017年下半年 内存按字节编址&#xff0c;若存储容量为32K*8bit的存储芯片构成地址从A0000H到 DFFFFH的内存&#xff0c;至少需要____片芯片。 解析&#xff1a; DFF…

《Netty》从零开始学netty源码(五十二)之PoolThreadCache

PoolThreadCache Netty有一个大的公共内存容器PoolArena&#xff0c;用来管理从操作系统中获得的内存&#xff0c;在高并发下如果所有线程都去这个大容器获取内存它的压力是非常大的&#xff0c;所以Netty为每个线程建立了一个本地缓存&#xff0c;即PoolThreadCache&#xff…

ReentrantLock实现原理-非公平锁

在线程间通信方式2一节中&#xff0c;我们了解了Lock&#xff0c;Condition和ReentrantLock&#xff0c;学习了简单使用Condition和RentrantLock完成线程间通信&#xff0c;从文章中我们了解到ReentrantLock是Lock接口的一个最常用的实现类&#xff0c;ReentrantLock是独占锁&a…

WEBPACK和ROLLUP构建前端工具库

1. WEBPACK webpack 提供了构建和打包不同模块化规则的库&#xff0c;只是需要自己去搭建开发底层架构。vue-cli&#xff0c;基于 webpack &#xff0c; vue-cli 脚手架工具可以快速初始化一个 vue 应用&#xff0c;它也可以初始化一个构建库。 2. ROLLUP rollup 是一个专门…