JavaScript中判断变量的类型

news2025/1/11 13:00:55
数据类型

在 JavaScript 中有 8 种基本的数据类型(7 种原始类型和 1 种引用类型),它们分别是:
原始类型/基本类型
NumberBigIntStringBooleannullundefinedSymbol

引用类型/复杂类型:
Object

typeof 运算符

typeof运算符返回参数的类型。当我们想要分别处理不同类型值的时候,或者想快速进行数据类型检验时,非常有用。

typeof x 的调用会以字符串的形式返回数据类型:
注意:返回的结果是字符串,而且全部都是小写

      console.log(typeof 0); // "number"
      console.log(typeof 10n); // "bigint"
      console.log(typeof "foo"); // "string"
      console.log(typeof true); // "boolean"
      console.log(typeof undefined); // "undefined"
      console.log(typeof Symbol("id")); // "symbol"

      function cb() {
        console.log("hello");
      }
      console.log(typeof cb); //"function"

      console.log(typeof null); //"object"
      console.log(typeof [1, 2, 3]); //"object"
      console.log(typeof { a: "a", n: "b" }); //"object"

      let map = new Map();
      let set = new Set();
      console.log(typeof map); //"object"
      console.log(typeof set); //"object"
      console.log(typeof /[0-9]/); //"object"
      console.log(typeof new Date()); //"object"

根据上面的结果可以发现,下面的六种基本类型以及函数类型,typeof可以正确的区分:

      console.log(typeof 0); // "number"
      console.log(typeof 10n); // "bigint"
      console.log(typeof "foo"); // "string"
      console.log(typeof true); // "boolean"
      console.log(typeof undefined); // "undefined"
      console.log(typeof Symbol("id")); // "symbol"
      
      function cb() {
        console.log("hello");
      }
      console.log(typeof cb); //"function"

但是对于null数组,以及普通对象正则以及mapset等类型,则不能更精细的区分,返回的都是object
其中typeof null 会返回 "object" —— 这是 JavaScript 编程语言的一个错误,实际上它并不是一个 object

instanceof 操作符

instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上,使用方法如下:

//实例对象  instanceof  构造函数
object instanceof constructor

返回结果为true或者false
如果构造函数的prototype属性在object的原型链上,就返回true,否则返回false

      console.log([1, 2, 3] instanceof Array); //true
      console.log({ a: "a", n: "b" } instanceof Object); //true
      console.log(null instanceof Object); //false
      
      let map = new Map();
      let set = new Set();
      let time = new Date();
      console.log(map instanceof Map); //true
      console.log(set instanceof Set); //true
      console.log(time instanceof Date); //true
      console.log(/[0-9]/ instanceof RegExp); //true

使用instanceof可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型:
在这里插入图片描述

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

      // 左边是对象,右边是构造函数
      // 原理就是判断左边对象的原型链上,有没有构造函数的prototype属性的对象
      function myInstanceOf(left, right) {
        if (typeof left !== "object" || left === null) return false;
        let obj = Object.getPrototypeOf(left);
        while (obj) {
          if (right.prototype === obj) return true;
          obj = Object.getPrototypeOf(obj);
        }
        return false;
      }
更通用的数据类型检测

Object.prototype.toString(),调用该方法,统一返回格式“[object Xxx]”的字符串:

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]"

简单说下我的理解,在js中除了基本数据类型以外,其他的类型都可视为对象类型,当然也可以使用包装类,将基本类型包装成对象,比如字符串字面量在调用toUpperCase()方法时就会自动将其包装为String对象,使得你可以调用字符串方法:

let str = "hello";
console.log(str.toUpperCase()); // 输出 "HELLO"

可以认为所有的对象都继承自Object.prototype对象,那么所有的对象类型共享从Object.prototype继承来的属性和方法,比如toString()方法。

Object.prototype.toString() 返回 “[object Type]”,这里的 Type 是对象的类型。如果对象有
Symbol.toStringTag 属性,其值是一个字符串,则它的值将被用作 Type。许多内置的对象,包括 Map 和Symbol,都有 Symbol.toStringTag。一些早于 ES6 的对象没有
Symbol.toStringTag,但仍然有一个特殊的标签。它们包括(标签与下面给出的类型名相同):
在这里插入图片描述
arguments 对象返回 “[object Arguments]”。其他所有内容,包括用户自定义的类,除非有一个自定义的 Symbol.toStringTag,否则都将返回 "[object Object]"。

Object.prototype.toString()返回的类型是根据对象的Symbol.toStringTag 属性来的,对于用户自定义类,toStringTag默认使用"Object"标签。

class ValidatorClass {}

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

看下面的代码:
这里我们自定义类,接着设置自己的自定义标签。然后创建ValidatorClass 类对应的实例对象v,使用Object.prototype.toString()判断类型,可以发现,这个过程是从v实例的构造函数中的Symbol.toStringTag接口中寻找的。

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

let v = new ValidatorClass();
console.log(Object.prototype.toString.call(v)); // "[object Validator]"

这也说明,如果是字符串,数字类型,应该是去String,Number构造函数中找对应的接口。

ECMA文档的描述:
该属性值是一个字符串,用来创建对象的默认字符串描述。可以通过内置方法Object.prototype.toString()获取。
在这里插入图片描述

另外关于为什么需要使用call()绑定到目标对象:
这是因为js中的其他对象都继承自Object.prototype,比如String类型,Array类型,都可以调用toString()方法,但是同时他们也重写了toString()方法,和最初的,即来自Object.prototype对象的toString()不一样了,比如Number.prototype.toString(),返回的是表示该数字值的字符串:

      let n = 123;
      console.log(n.toString()); // "123"
      console.log(typeof n.toString()); //string

所以需要使用最初的toString()方法,同时改变其this的指向。

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

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

相关文章

C++开发基础之深入理解C++中的两种单例模式实现——线程安全与效率的权衡

引言: 单例模式是设计模式中的一种,它保证一个类仅有一个实例,并提供一个全局访问点。在C中,实现单例模式的方式多种多样,但随着多线程应用的普及,如何确保单例模式在多线程环境下的线程安全性成为了一个重…

深度学习--图像分割UNet介绍及代码分析

UNet介绍 参考UNet网络介绍整体架构UNet过程输入编码器(下采样)中间特征表示解码器(上采样)输出 代码详解unetUP和Unet关系上采样模块——unetUp用于图像分割的卷积神经网络(CNN)架构模块——Unet类的定义初…

使用 Manim 创建一个二维坐标平面【NumberPlane】

NumberPlane 是 Manim 中用于创建一个二维坐标平面的类。它可以帮助用户在场景中可视化坐标轴、网格线以及其他数学概念。具体来说,它的功能包括: 坐标轴:NumberPlane 提供了 x 轴和 y 轴,通常是中心对称的,允许用户清…

深入探究Python反序列化漏洞:原理剖析与实战复现

在现代应用程序开发中,Python反序列化漏洞已成为一个备受关注的安全问题。反序列化是Python中用于将字节流转换回对象的过程,但如果没有妥善处理,攻击者可以通过精心构造的恶意数据,利用反序列化漏洞执行任意代码,进而…

前端day4-表单标签

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>day4-表单</title> </head> <body&g…

# 基于MongoDB实现商品管理系统(2)

基于MongoDB实现商品管理系统&#xff08;2&#xff09; 基于 mongodb 实现商品管理系统之准备工作 1、案例需求 这里使用的不是前端页面&#xff0c;而是控制台来完成的。 具体的需求如下所示&#xff1a; 运行 查询所有 通过id查询详情 添加 - 通过id删除 2、案例分析 程…

进程创建,进程消亡

虚拟地址&#xff1a;通过虚拟技术&#xff0c;将外部存储设备的一部分空间&#xff0c;划分给系统&#xff0c;作为在内存不足时临时用作数据缓存。当内存耗尽时&#xff0c;电脑就会自动调用硬盘来充当内存&#xff0c;以缓解内存的紧张。 练习: 编写一个代码实现,一个父…

OGG转MP3音频格式转换:6种免费音频转换器推荐

在如今的数字音乐时代&#xff0c;不同音频格式的兼容性问题常常让我们感到困扰。其中&#xff0c;OGG和MP3是两种常见的音频格式&#xff0c;但由于设备和平台的支持问题&#xff0c;我们经常需要将OGG转换为MP3格式。 本文将为您详细介绍OGG和MP3的区别&#xff0c;为什么需要…

Spring Boot集成protobuf快速入门Demo

1.什么是protobuf&#xff1f; Protobuf&#xff08;Protocol Buffers&#xff09;是由 Google 开发的一种轻量级、高效的数据交换格式&#xff0c;它被用于结构化数据的序列化、反序列化和传输。相比于 XML 和 JSON 等文本格式&#xff0c;Protobuf 具有更小的数据体积、更快…

数据结构:队列(含源码)

目录 一、队列的概念和结构 二、队列的实现 头文件 初始化 入队列和出队列 获取队头队尾元素 队列有效数据数及队列判空 队列的销毁 完整源码 dl.h dl.c 一、队列的概念和结构 队列是一种只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性…

重生之我 学习【数据结构之顺序表(SeqList)】

⭐⭐⭐ 新老博友们&#xff0c;感谢各位的阅读观看 期末考试&假期调整暂时的停更了两个多月 没有写博客为大家分享优质内容 还容各位博友多多的理解 美丽的八月重生之我归来 继续为大家分享内容 你我共同加油 一起努力 ⭐⭐⭐ 数据结构将以顺序表、链表、栈区、队列、二叉树…

多米诺和托米诺平铺

有两种形状的瓷砖&#xff1a;一种是2 x 1的多米诺形&#xff0c;另一种是形如L的托米诺形。两种形状都可以旋转。 给定整数 n &#xff0c;返回可以平铺 2 x n 的面板的方法的数量。返回对 10^9 7 取模 的值。 平铺指的是每个正方形都必须有瓷砖覆盖。两个平铺不同&#xff…

maven常用命令与常见问题汇总

文章目录 一、IDEA 下载依赖包源码报错Sources not found for:xxxx二、常用命令1、打包 一、IDEA 下载依赖包源码报错Sources not found for:xxxx 解决方案&#xff1a; 方案1、在 terminal 运行 mvn dependency:resolve -Dclassifiersources 命令 方案2、右键特定的pom文件…

论文概览 |《IJGIS》2024 Vol.38 issue4

本次给大家整理的是《International Journal of Geographical Information Science》杂志2024年第38卷第4期的论文的题目和摘要&#xff0c;一共包括8篇SCI论文&#xff01; 论文1 knowledge-constrained large language model interactable with GIS: enhancing public risk …

笔试题 day1

目录 快速io 统计2的个数 两个数组的交集 点击消除 快速io import java.util.*; import java.io.*;public class Main {public static PrintWriter out new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));public static Read in new Read();publ…

瑞_Linux防火墙相关命令_Windows远程连接虚拟机的服务失败_Linux防火墙端口开放

&#x1f64a; 前言&#xff1a;博主在学习使用虚拟机的过程中&#xff0c;常常碰到 Windows 远程连接虚拟机的服务失败的问题。比如想要在主机上连接虚拟机中的 MongoDB 服务的时候&#xff0c;服务器或者虚拟机一般都会默认开启防火墙&#xff0c;则会导致远程连接失败&#…

做一个能和你互动玩耍的智能机器人之七-接入对话和大模型

接入科大迅飞的语音识别&#xff1a; private void printResult(RecognizerResult results) {String text JsonParser2.parseIatResult(results.getResultString());String sn null;// 读取json结果中的sn字段try {JSONObject resultJson new JSONObject(results.getResult…

如何忽略已经提交到 Git 仓库中的文件

文章目录 前言一、确认文件是否已经被提交二、确认 .git 文件存在三、修改 .git/info/exclude 文件四、修改文件名五、提交和推送六、验证总结 前言 在日常开发中&#xff0c;我们常常会遇到这样的情况&#xff1a;不小心将不应追踪的文件提交到了 Git 仓库中&#xff0c;例如…

LabVIEW中的Reverse String函数与字节序转换

在LabVIEW中&#xff0c;数据的字节序&#xff08;也称为端序&#xff09;问题通常出现在数据传输和存储过程中。字节序可以分为大端&#xff08;Big-Endian&#xff09;和小端&#xff08;Little-Endian&#xff09;&#xff0c;它们分别表示高字节存储在低地址和低字节存储在…

培训第二十二天(mysql数据库主从搭建)

上午 1、为mysql添加开机启动chkconfig [rootmysql1 ~]# chkconfig --list //列出系统服务在不同运行级别下的启动状态注&#xff1a;该输出结果只显示 SysV 服务&#xff0c;并不包含原生 systemd 服务。SysV 配置数据可能被原生 systemd 配置覆盖。 要列出 systemd 服务…