进阶理解——typeof 、instanceof
typeof 、instance of
- 先聊聊JavaScript基本类型
- 数据类型
- 5种含值数据类型
- 2种不含值类型
- 6种类型的*对象*
- typeof
- instanceof
- 总结
- 进一步扩展一下
- 具体讨论一下typeof局限性
- 扩展判断方法
很多时候,回头望,理解会更深刻,也希望能帮助一些初学的同学理解。
先聊聊JavaScript基本类型
以下类型一定注意区别
数据类型
5种含值数据类型
在 JavaScript 中有 5 种不同的可以包含值的数据类型:
stringnumberbooleanobjectfunction
2种不含值类型
nullundefined
6种类型的对象
ObjectDateArrayStringNumberBoolean
typeof
您可以使用 typeof 运算符来确定 JavaScript 变量的数据类型,返回对应数据类型字符串。
这是官方的一句话,细品,这说明什么?
说明:我们可以通过这个运算符判断出含值和不含值的数据类型。
而类似于Array、Date等类型的对象,我们无法具体判断,只能判断出时一个object数据类型。
typeof "Bill" // 返回 "string"
typeof 3.14 // 返回 "number"
typeof NaN // 返回 "number"
typeof false // 返回 "boolean"
typeof [1,2,3,4] // 返回 "object"
typeof {name:'Bill', age:19} // 返回 "object"
typeof new Date() // 返回 "object"
typeof function () {} // 返回 "function"
typeof myCar // 返回 "undefined" *
typeof null // 返回 "object"
需要注意的是:
- NaN 的数据类型是数字
- 数组的数据类型是对象
- 日期的数据类型是对象
- null 的数据类型是 object
- 未定义变量的数据类型为 undefined *
- 未赋值的变量的数据类型也是 undefined *
看到这,心里可能会有疑惑,说好的可以判断数据类型,null为什么是object?
对咯。就他最特别,这实际上是语言设计上的一个错误,并且由于历史原因一直保留到了现在。所以他是特立独行的—一个bug。
原理是这样的,不同的对象在底层都表示为二进制,
在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型,
null 的二进制表示是全 0,自然前三位也是 0,
所以执行 typeof 时会返回“object”。
想了解可以看看本链接
说到这里大家是不是明明白白了,除了一个bug null,typeof只能判断含值和不含值的数据类型。
像Array、Data等等这些对象的类型就无法具体判断了。
那么还有别的办法吗?
答案是肯定的
instanceof
instanceof 是一个二元运算符,用于测试构造函数的 prototype 属性是否出现在对象的原型链上。
如果对象是指定的构造函数创建的实例,或者继承自该构造函数的原型链,instanceof 运算符会返回 true。
class Car {}
const myCar = new Car();myCar instanceof Car // true
myCar instanceof Object // true(因为Car继承自Object)[] instanceof Array // true
([]) instanceof Object // true(因为所有的数组都是对象)function MyFunc() {}
const myFunc = new MyFunc();myFunc instanceof MyFunc // true
myFunc instanceof Object // true(因为所有函数都是对象)// 注意:字面量形式创建的基本类型不是任何构造函数的实例
'hello' instanceof String // false
42 instanceof Number // false
true instanceof Boolean // false
由于 instanceof 是基于原型链进行检查的,它能够用于检测复杂对象类型,比如自定义对象和内置对象实例(如 Array、Date 等)。然而,它不适用于基本数据类型。
总结
- 使用 typeof 来
检测基本数据类型,除了 null。 - 使用 instanceof 来
检查一个对象是否是某个特定类(或构造函数)的实例,或者说检测一个对象是否继承自某个原型。 - 要准确地判断一个变量是否为 null,应使用严格等于比较 (=== null)。
- 对于其他更复杂的类型检查需求,可能需要使用其他方法,比如 Object.prototype.toString.call(value)。
关于第三个,这里说一下undefined 与 null 的区别
undefined 和 null 值相等但类型不同:
typeof undefined // undefined
typeof null // objectnull === undefined // false
null == undefined // true
ps:如果有原型和原型链不太熟悉的,我会抽空补一篇,放下链接,还没有就说明还没写。。。
进一步扩展一下
具体讨论一下typeof局限性
typeof 运算符对于基本数据类型通常很有效,但在某些情况下,它并不能提供足够的信息来准确判断值的类型。以下是一些 typeof 无法准确检测的情况:
- 区分对象类型:typeof 将任何对象类型都返回为 “object”,不论它是一个普通的对象字面量、数组、正则表达式还是其他内置对象。
typeof []; // "object",但实际上是 Array
typeof {}; // "object",普通对象
typeof /regex/; // "object",在非标准的浏览器中可能返回 "function"
typeof new Date(); // "object",但实际上是 Date
- null 值:typeof null 返回 “object”,这实际上是一个长期存在的 JavaScript 错误。
typeof null; // "object",应该是 `null`
3.区分数组和普通对象:如上所述,数组和普通对象都返回 “object”。
typeof []; // "object",没有区分它是 Array
4.函数对象和普通对象:虽然 typeof 可以识别函数对象返回 “function”,但无法区分不同种类的函数(例如普通函数、箭头函数、异步函数、生成器函数等)。
typeof function(){}; // "function"
typeof (() => {}); // "function"
typeof async function(){}; // "function"
typeof function*(){}; // "function"
5.原始包装对象和原始值:对于字符串、数字和布尔值的原始包装对象,typeof 会将其视为 “object”,而非它们各自的原始类型。
typeof new String("string"); // "object"
typeof new Number(100); // "object"
typeof new Boolean(true); // "object"
6.特殊对象:typeof 对于特殊的对象,比如 Map、Set、WeakMap 和 WeakSet 等也只能返回 “object”。
typeof new Map(); // "object"
typeof new Set(); // "object"
- Undefined vs. undeclared:虽然 typeof 在处理未声明变量时不会抛出错误,并且会返回 “undefined”,但它无法区分一个变量是未定义还是未声明。
let x;
typeof x; // "undefined"
typeof y; // "undefined",即使 y 没有被声明
由于这些局限性,当需要更精确地判断复杂数据类型时,开发者通常会采用其他方法,如 instanceof 检查、Object.prototype.toString.call() 方法,或者在现代JavaScript框架和库中定义的自己的类型判断函数。
扩展判断方法
JavaScript 提供了 Array.isArray() 方法来特别判断一个值是否为数组。它比 typeof 更精确,因为 typeof 对于数组会返回 “object”。
对于其他类型的检查,虽然没有内置的类似 Array.isArray() 这样针对特定数据结构的方法,但我们可以使用 Object.prototype.toString.call() 来获取对象的类(class)信息:
let toString = Object.prototype.toString;// 使用 toString 方法检测不同类型
toString.call([]); // "[object Array]"
toString.call({}); // "[object Object]"
toString.call(''); // "[object String]"
toString.call(new Date()); // "[object Date]"
toString.call(1); // "[object Number]"
toString.call(true); // "[object Boolean]"
toString.call(function(){}); // "[object Function]"
toString.call(/regex/); // "[object RegExp]"
toString.call(null); // "[object Null]"
toString.call(undefined); // "[object Undefined]"
通过上面的方法,你可以构建自己的类型检查函数,就像 Array.isArray() 那样。例如:
function isDate(value) {return toString.call(value) === '[object Date]';
}
此外,ES6 引入了几个新的全局对象,也带来了类似的静态方法用于确定值是否为特定类型的实例:
- ArrayBuffer.isView(value): 检查一个值是否是类型化数组视图,比如 Int8Array 实例或其他类型化数组视图。
ArrayBuffer.isView(new Int8Array()); // true
ArrayBuffer.isView(new Float32Array()); // true
ArrayBuffer.isView([]); // false
- Number.isNaN(value): 确定传入的值是否是 NaN,且更准确地与全局 isNaN() 函数区分开来。
Number.isNaN(NaN); // true
Number.isNaN('NaN'); // false
- Number.isInteger(value): 判断给定的参数是否为整数。
Number.isInteger(1); // true
Number.isInteger(1.5); // false
- Number.isFinite(value): 检查一个值是否为有限数。
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite(1); // true
这些方法为不同类型的检测提供了官方支持并保证了结果的准确性。但仍然没有像 Array.isArray() 那样的方法用于直接检测 Map, Set, WeakMap, 或 WeakSet 等数据类型。在这些情况下,通常需要使用上述 Object.prototype.toString.call() 方式来进行类型的判断。
相关文章:
进阶理解——typeof 、instanceof
typeof 、instance of 先聊聊JavaScript基本类型数据类型5种含值数据类型2种不含值类型 6种类型的*对象* typeofinstanceof总结进一步扩展一下具体讨论一下typeof局限性扩展判断方法 很多时候,回头望,理解会更深刻,也希望能帮助一些初学的同学…...
不同类型的生物反应器在支架成熟过程中具有哪些特点和应用?
3D Bioprinting of Human Tissues: Biofabrication, Bioinks, and Bioreactors是发表于《International Journal of Molecular Sciences》的一篇综述,详细介绍了3D生物打印人体组织的相关技术进展,包括数据处理、生物打印技术、生物墨水配方、生物反应器…...
8. Spring Ai之入门到精通(超级详细)
简介 2024年5月30号Spring AI 的 1.0.0 里程碑 1 版本发布。表明版本已正在巩固,并且大部分主要错误和问题已经解决,API基本已确定,不会发生很大的变化。 在与大模型集成方面,继LangChain4j之后,又一重大的框架诞生。标…...
寄存器和硬件的关系
寄存器也是一种存储器,只不过普通的存储器只能写和读。里面的数据并没有赋予什么实际意义。但是寄存器就不一样了,寄存器的每一位数据,都对应了硬件电路的状态。寄存器和外设的硬件电路,是可以进行互动的。所以,程序到…...
【WEB】ctfshow-萌新-web9-15
文章目录 题目介绍:题目分析:payload: 题目介绍: ctfshow-萌新计划-web9-15 <?php # flag in config.php include("config.php"); if(isset($_GET[c])){$c $_GET[c];if(preg_match("/system|exec|highlight…...
【Vulnhub靶场AI-WEB-1.0打靶教程】
第一步:查看虚拟机的ip 第二步:扫描ip下开放的80端口 第三步:扫描查到的ip地址下的目录 第四步:访问查到的目录 访问robot.txt 第五步:访问robot.txt显示出的目录 第六步:打开kali终端,使用sqlmap功能 sq…...
html实现酷炫美观的可视化大屏(十种风格示例,附源码)
文章目录 完整效果演示1.蓝色流线风的可视化大屏1.1 大屏效果1.2 大屏代码1.3 大屏下载 2.地图模块风的可视化大屏2.1 大屏效果2.2 大屏代码2.3 大屏下载 3.科技轮动风的可视化大屏3.1 大屏效果3.2 大屏代码3.3 大屏下载 4.蓝色海洋风的可视化大屏4.1 大屏效果4.2 大屏代码4.3 …...
【C++BFS算法 二分查找】2812. 找出最安全路径
本文涉及知识点 CBFS算法 C二分查找 LeetCode2812. 找出最安全路径 给你一个下标从 0 开始、大小为 n x n 的二维矩阵 grid ,其中 (r, c) 表示: 如果 grid[r][c] 1 ,则表示一个存在小偷的单元格 如果 grid[r][c] 0 ,则表示一…...
轻触开关 KH-4.5X4.5X5.5H-STM
品 牌: kinghelm(金航标) 厂家型号: KH-4.5X4.5X5.5H-STM 封装: SMD 商品毛重: 0.317克(g) 包装方式: 编带...
3.redis客户端
1.命令行客户端 在安装redis的时候就已经安装好了,就是redis-cli redis-cli -h 127.0.0.1 -p 6379 -a 123456 -a 表示密码 -h 表示ip,不配置默认为本机 127.0.0.1 -p 表示端口,不配置默认为 6379 进入后可以输入ping,返回pong代表…...
Rust配置国内源,解决安装依赖慢问题
温馨提示:最新内容仅在原文更新。 国内源使用字节的RsProxy https://rsproxy.cn/ 解决rust-analyzer加载时间过长(请参考本文) 配置环境变量 Mac export RUSTUP_DIST_SERVER"https://rsproxy.cn" export RUSTUP_UPDATE_ROOT"https://rsproxy.cn/r…...
AI学习指南机器学习篇- Q学习的参数与调优
AI学习指南机器学习篇- Q学习的参数与调优 在强化学习领域中,Q学习是一种经典的算法,可以用来解决各种问题,包括游戏和机器人控制等。Q学习算法的性能很大程度上取决于一些重要的参数,例如学习率和折扣因子。本文将介绍这些参数的…...
《小迪安全》学习笔记02
域名默认存放目录和IP默认存放目录不一样。 IP地址是WWW文件里的,域名访问是WWW里的一个子目录里的(比如是blog)。 Nmap: Web源码拓展 拿到一个网站的源码,要分析这几个方面↑。 不同类型产生的漏洞类型也不一样 在网站中&…...
C语言:自定义类型进阶(结构体、联合体、枚举)
自定义类型(结构体、联合体、枚举) 一、结构体(一)结构体的内存对齐1、结构体内存对齐规则(1)引子(2)offsetof 宏函数(3)内存对齐原理(4ÿ…...
SPSSAU | 最好最差权重BWM原理及案例实操分析
BWM(best-worse-method,最好最差法)是一种多准则决策方法,由Jafar Rezaei于2015年提出,其通常用于确定决策标准的权重。其原理是比如5个指标,如果以前AHP就需要5个指标两两的相对重要性数据。但是现在简化为…...
docker安装elasticsearch(es)最新版本
docker安装elasticsearch(es) docker官网 https://hub.docker.com/ https://www.cnblogs.com/balloon72/p/13177872.html 1、拉取最新项目elasticsearch docker pull elasticsearch:8.14.3lscpu 查看架构 2、构建环境 mkdir -p /data/elasticsear…...
02 RabbitMQ:下载安装
02 RabbitMQ:下载&安装 1. 下载&安装1.1. 官网1.2. Docker方式1.2.1. 下载镜像1.2.2. 启动1.2.3. 登录验证 1. 下载&安装 1.1. 官网 RabbitMQ: One broker to queue them all | RabbitMQ 1.2. Docker方式 1.2.1. 下载镜像 # docker pull 镜像名称[…...
mmcv库出现No module named ‘mmcv._ext
遇到 "No module named mmcv._ext" 这个错误通常意味着你的 Python 环境中缺少 mmcv 库的扩展模块 _ext。mmcv(MMDetection 训练工具箱的核心库)通常依赖于 _ext 模块来提供一些高性能的操作,这些操作是用 C/C 实现的,并…...
防止xss(跨站脚本攻击)
1、输出数据时进行转义:这是最基本的预防措施。确保在输出数据到HTML时对特殊字符进行适当的转义,以防止它们被解释为HTML或JavaScript代码。PHP中可以使用htmlspecialchars()、strip_tags()、htmlentities函数来实现这一点。 echo htmlspecialchars($d…...
django小型超市库存与销售管理系统-计算机毕业设计源码46608
摘 要 随着信息技术的快速发展,超市库存与销售管理面临着前所未有的挑战与机遇。为了提升超市的运营效率,优化库存管理,并增强销售数据的分析能力,我们基于Django框架设计并开发了一套小型超市库存与销售管理系统。该系统充分利用…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
6.9-QT模拟计算器
源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...
