JS面试常见问题——数据类型篇
这几周在进行系统的复习,这一篇来说一下自己复习的JS数据结构的常见面试题中比较重要的一部分
文章目录
- 一、JavaScript有哪些数据类型
- 二、数据类型检测的方法
- 1. typeof
- 2. instanceof
- 3. constructor
- 4. Object.prototype.toString.call()
- 5. type null会被判断为Object,为什么
- 6. typeof NaN的结果是什么
- 三、判断数组的方式有哪些
- 1. Object.prototype.toString.call()
- 2. 通过原型链判断
- 3. 通过ES6的Array.isArray()做判断
- 4. 通过instanceof判断
- 5. 通过Array.prototype.isPrototypeOf()
- 四、null和undefined的区别
- 五、instanceof操作符的实现原理及实现
- 六、为什么0.1+0.2 !== 0.3,如何让其相等
- 1. 原因
- 2. 如何解决
- 七、==操作符的强制类型转换规则
- 八、Object.is()与比较操作符“=== ”、“ ==”的区别
- 九、其他值到字符串的转换规则
- 十、其他值到数字值的转换规则
- 十一、其他值到布尔类型的值的转换规则
- 十二、isNaN和Number.isNaN函数的区别
- 十三、JavaScript中如何进行隐式类型转换
- 1. ToPrimitive
- 2. 隐式转换规则
- 3. +操作符什么时候用于字符串拼接
一、JavaScript有哪些数据类型
八种:Number String Boolean Null undefined Object Symbol BigInt
Symbol & BigInt 是ES6新增的数据类型
- Symbol 代表创建后独一无二且不可变的数据类型;主要是为了解决可能出现全局变量冲突的问题
- BigInt是一种数字类型,可以表示任意精度格式的整数,使用BigInt可以安全地存储和操作大整数,即使这个数超出Number能够表示的安全整数范围
分类:原始数据类型 & 引用数据类型
栈:Number String Boolean Null Undefined(原始数据类型)
堆:Object(引用数据类型)(对象、数组、函数)
两种类型的区别在于存储位置的不同:
- 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
- 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
数据结构和操作系统中
堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:
● 在数据结构中,栈中数据的存取方式为先进后出。
● 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。
在操作系统中,内存被分为栈区和堆区:
● 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
● 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
二、数据类型检测的方法
1. typeof
注:数组、对象、null都会被判断为Object
2. instanceof
可以正确判断对象的类型,不能判断基本数据类型;可以用来测试一个对象在其原型链中是否存在一个构造函数的prototype属性
内部运行机制是判断在其原型链中能否找到该类型的原型
3. constructor
判断数据的类型;对象实例通过constructor对象访问它的构造函数;如果创建一个对象来改变他的原型,constructor就不能用来判断数据类型了
4. Object.prototype.toString.call()
使用 Object 对象的原型方法 toString 来判断数据类型
同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?
这是因为toString是Object的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。
5. type null会被判断为Object,为什么
在 JavaScript 第一个版本中,所有值都存储在 32 位的单元中,每个单元包含一个小的 类型标签(1-3 bits) 以及当前要存储值的真实数据。类型标签存储在每个单元的低位中,共有五种数据类型:
000: object - 当前存储的数据指向一个对象。
1: int - 当前存储的数据是一个 31 位的有符号整数。
010: double - 当前存储的数据指向一个双精度的浮点数。
100: string - 当前存储的数据指向一个字符串。
110: boolean - 当前存储的数据是布尔值。
有两种特殊数据类型:
● undefined的值是 (-2)30(一个超出整数范围的数字);
● null 的值是机器码 NULL 指针(null 指针的值全是 0)
在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回 object。
6. typeof NaN的结果是什么
返回的结果:number
NaN 指“不是一个数字”(not a number),NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果”。
NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不成立)的值。而 NaN !== NaN 为 true。
三、判断数组的方式有哪些
1. Object.prototype.toString.call()
Object.prototype.toString.call(obj).slice(8,-1) === 'Array';
2. 通过原型链判断
obj.__proto__ === Array.prototype;
3. 通过ES6的Array.isArray()做判断
4. 通过instanceof判断
5. 通过Array.prototype.isPrototypeOf()
四、null和undefined的区别
undefined代表的含义是未定义,当一个变量没有任何数据时也是undefined,undefined是原始数据类型之一,可以直接把undefined赋值给变量或函数返回;被迫的替代方案
null是空对象,需要主动使用,没有声明不会出现;空
判断null和undefined时需要使用严格判断(===)
五、instanceof操作符的实现原理及实现
instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
function myInstanceof(left, right) {// 获取对象的原型let proto = Object.getPrototypeOf(left)// 获取构造函数的 prototype 对象let prototype = right.prototype; // 判断构造函数的 prototype 对象是否在对象的原型链上while (true) {if (!proto) return false;if (proto === prototype) return true;// 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型proto = Object.getPrototypeOf(proto);}
}
六、为什么0.1+0.2 !== 0.3,如何让其相等
1. 原因
计算机是通过二进制的方式存储数据的,所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。0.1的二进制是0.0001100110011001100…(1100循环),0.2的二进制是:0.00110011001100…(1100循环),这两个数的二进制都是无限循环的数。
但是在 JavaScript 中只有一种数字类型:Number,它的实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数。在二进制科学表示法中,双精度浮点数的小数部分最多只能保留52位,再加上前面的1,其实就是保留53位有效数字,剩余的需要舍去,遵从“0舍1入”的原则。
根据这个原则,0.1和0.2的二进制数相加,再转化为十进制数就是:0.30000000000000004。
- 第一部分(蓝色):用来存储符号位(sign),用来区分正负数,0表示正数,占用1位
- 第二部分(绿色):用来存储指数(exponent),占用11位
- 第三部分(红色):用来存储小数(fraction),占用52位
2. 如何解决
一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3
七、==操作符的强制类型转换规则
- 一个布尔值,将其转换为数字比较
- 一个字符串,一个数字、布尔值或null,将字符串转换为数字比较。
- 一个对象,一个字符串、数字或符号,将对象转换为原始值比较。
对象转换为原始值的规则如下:
- 如果对象有valueOf方法并返回基本类型的值,则使用该值进行比较。
- 如果valueOf方法返回的仍然是对象,则调用对象的toString方法,并使用返回的字符串进行比较。
- 如果对象没有valueOf和toString方法,或者返回的不是基本类型的值,则抛出TypeError异常。
- 一个null,一个undefined,则相等。
- 一个NaN,一个不是NaN,则相等
- 一个数字0,一个字符串且内容为非空,则将数字0转换为字符串再进行比较。
- 其他情况下,将操作数都转换为数字再进行比较。
需要注意的是,如果两个都是对象,则比较的是它们的引用是否相等,不会进行强制类型转换。
八、Object.is()与比较操作符“=== ”、“ ==”的区别
- 使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
- 使用三等号(===)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。
- 使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 是相等的。
九、其他值到字符串的转换规则
- Null 和 Undefined 类型 ,null 转换为 “null”,undefined 转换为 “undefined”,
- Boolean 类型,true 转换为 “true”,false 转换为 “false”。
- Number 类型的值直接转换,不过那些极小和极大的数字会使用指数形式。
- Symbol 类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误。
- 对普通对象来说,除非自行定义 toString() 方法,否则会调用 toString()(Object.prototype.toString())来返回内部属性 [[Class]] 的值,如"[object Object]"。如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值。
十、其他值到数字值的转换规则
- Undefined 类型的值转换为 NaN。
- Null 类型的值转换为 0。
- Boolean 类型的值,true 转换为 1,false 转换为 0。
- String 类型的值转换如同使用 Number() 函数进行转换,如果包含非数字值则转换为 NaN,空字符串为 0。
- Symbol 类型的值不能转换为数字,会报错。
- 对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。
为了将值转换为相应的基本类型值,抽象操作 ToPrimitive 会首先(通过内部操作 DefaultValue)检查该值是否有valueOf()吗方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString() 的返回值(如果存在)来进行强制类型转换。
如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
十一、其他值到布尔类型的值的转换规则
假值: undefined null false +0、-0 和 NaN “”
假值的布尔强制类型转换结果为false;从逻辑上说,假值表以外的应该都是真值
十二、isNaN和Number.isNaN函数的区别
- 函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true,会影响 NaN 的判断。
- 函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。
十三、JavaScript中如何进行隐式类型转换
1. ToPrimitive
JavaScript 中每个值隐含的自带的方法,用来将值 (无论是基本类型值还是对象)转换为基本类型值。如果值为基本类型,则直接返回值本身;如果值为对象,
// @obj 需要转换的对象
// @type 期望的结果类型
ToPrimitive(obj,type)
type的值为number或者string。
(1)当type为number时规则如下:
● 调用obj的valueOf方法,如果为原始值,则返回,否则下一步;
● 调用obj的toString方法,后续同上;
● 抛出TypeError 异常。
(2)当type为string时规则如下:
- 调用obj的toString方法,如果为原始值,则返回,否则下一步;
- 调用obj的valueOf方法,后续同上;
- 抛出TypeError异常。
默认情况下:
- 如果对象为 Date 对象,则type默认为string;
- 其他情况下,type默认为number。
Date 以外的对象,转换为基本类型的大概规则可以概括为一个函数:
var objToNumber = value => Number(value.valueOf().toString())
objToNumber([]) === 0
objToNumber({}) === NaN
2. 隐式转换规则
隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间
- +操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。
- -、*、\操作符NaN也是一个数字
- ==操作符两边的值都尽量转成number
- <>如果两边都是字符串,则比较字母表顺序;其他情况下,转为数字再比较;对象会被ToPrimitive转换为基本类型再进行转换
3. +操作符什么时候用于字符串拼接
如果 + 的其中一个操作数是字符串(或者通过以上步骤最终得到字符串),则执行字符串拼接,否则执行数字加法
除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字。
|| 和 && 操作符的返回值
相关文章:

JS面试常见问题——数据类型篇
这几周在进行系统的复习,这一篇来说一下自己复习的JS数据结构的常见面试题中比较重要的一部分 文章目录 一、JavaScript有哪些数据类型二、数据类型检测的方法1. typeof2. instanceof3. constructor4. Object.prototype.toString.call()5. type null会被判断为Obje…...
创客匠人:如何通过创始人IP打造实现知识变现与IP变现的长效增长?
在流量红利逐渐消退的当下,创始人IP的价值愈发凸显。它不仅能够帮助中小企业及个人创业者突破竞争壁垒,还能成为企业品牌影响力的核心资产。然而,市场上IP孵化机构鱼龙混杂,如何选择一家真正具备长期价值的合作伙伴?创…...

【靶场】XXE-Lab xxe漏洞
前言 学习xxe漏洞,搭了个XXE-Lab的靶场 一、搭建靶场 现在需要登录,不知道用户名密码,先随便试试抓包 二、判断是否存在xxe漏洞 1.首先登录抓包 看到xml数据解析,由此判断和xxe漏洞有关,但还不确定xxe漏洞是否存在。 2.尝试xxe 漏洞 判断是否存在xxe漏洞 A.send to …...

开源项目实战学习之YOLO11:12.6 ultralytics-models-tiny_encoder.py
👉 欢迎关注,了解更多精彩内容 👉 欢迎关注,了解更多精彩内容 👉 欢迎关注,了解更多精彩内容 ultralytics-models-sam 1.sam-modules-tiny_encoder.py2.数据处理流程3.代码架构图(类层次与依赖)blocks.py: 定义模型中的各种模块结构 ,如卷积块、残差块等基础构建…...

Python[数据结构及算法 --- 栈]
一.栈的概念 在 Python 中,栈(Stack)是一种 “ 后进先出(LIFO)”的数据结构,仅允许在栈顶进行插入(push)和删除(pop)操作。 二.栈的抽象数据类型 1.抽象数…...

Unity VR/MR开发-开发环境准备
视频讲解链接: 【XR马斯维】UnityVR/MR开发环境准备【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

2025-06-08-深度学习网络介绍(语义分割,实例分割,目标检测)
深度学习网络介绍(语义分割,实例分割,目标检测) 前言 在开始这篇文章之前,我们得首先弄明白,什么是图像分割? 我们知道一个图像只不过是许多像素的集合。图像分割分类是对图像中属于特定类别的像素进行分类的过程,即像素级别的…...
Caliper 配置文件解析:config.yaml 和 fisco-bcos.json 附加在caliper中执行不同的合约方法
Caliper 配置文件解析:config.yaml 和 fisco-bcos.json Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO…...

【Ragflow】26.RagflowPlus(v0.4.0):完善解析逻辑/文档撰写模式全新升级
概述 在历经半个月的间歇性开发后,RagflowPlus再次迎来一轮升级,正式发布v0.4.0。 开源地址:https://github.com/zstar1003/ragflow-plus 更新方法 下载仓库最新代码: git clone https://github.com/zstar1003/ragflow-plus.…...

智能照明系统:具备认知能力的“光神经网络”
智能照明系统是物联网技术与传统照明深度融合的产物,其本质是通过感知环境、解析需求、自主决策的闭环控制,重构光与人、空间、环境的关系。这一系统由智能光源、多维传感器、边缘计算单元及云端管理平台构成,形成具备认知能力的“光神经网络…...
ubuntu系统 | docker+dify+ollama+deepseek搭建本地应用
1、docker 介绍与安装 docker安装:1、Ubuntu系统安装docker_ubuntu docker run-CSDN博客 docker介绍及镜像源配置:2、ubuntu系统docker介绍及镜像源和仓库配置-CSDN博客 docker常用命令:3、ubuntu系统docker常用命令-CSDN博客 docker compose安装:4、docker compose-CS…...
Docker 镜像上传到 AWS ECR:从构建到推送的全流程
一、在 EC2 实例中安装 Docker(适用于 Amazon Linux 2) 步骤 1:连接到 EC2 实例 ssh -i your-key.pem ec2-useryour-ec2-public-ip步骤 2:安装 Docker sudo yum update -y sudo amazon-linux-extras enable docker sudo yum in…...

SpringSecurity+vue通用权限系统
SpringSecurityvue通用权限系统 采用主流的技术栈实现,Mysql数据库,SpringBoot2Mybatis Plus后端,redis缓存,安全框架 SpringSecurity ,Vue3.2Element Plus实现后台管理。基于JWT技术实现前后端分离。项目开发同时采 …...
如何在Spring Boot中使用注解动态切换实现
还在用冗长的if-else或switch语句管理多个服务实现? 相信不少Spring Boot开发者都遇到过这样的场景:需要根据不同条件动态选择不同的服务实现。 如果告诉你可以完全摆脱条件判断,让Spring自动选择合适的实现——只需要一个注解,你是否感兴趣? 本文将详细介绍这种优雅的…...

短视频时长预估算法调研
weighted LR o d d s T p 1 − p ( 1 − p ) o d d s T p ( T p o d d s ∗ p ) o d d s p o d d s T o d d s odds \frac{Tp}{1-p} \newline (1-p)odds Tp \newline (Tp odds * p) odds \newline p \frac{odds}{T odds} \newline odds1−pTp(1−p)oddsTp(Tpodds…...
基于Java的离散数学题库系统设计与实现:附完整源码与论文
JAVASQL离散数学题库管理系统 一、系统概述 本系统采用Java Swing开发桌面应用,结合SQL Server数据库实现离散数学题库的高效管理。系统支持题型分类(选择题、填空题、判断题等)、难度分级、知识点关联,并提供智能组卷、在线测试…...
板凳-------Mysql cookbook学习 (十--2)
5.12 模式匹配中的大小写问题 mysql> use cookbook Database changed mysql> select a like A, a regexp A; ------------------------------ | a like A | a regexp A | ------------------------------ | 1 | 1 | --------------------------…...

设计模式域——软件设计模式全集
摘要 软件设计模式是软件工程领域中经过验证的、可复用的解决方案,旨在解决常见的软件设计问题。它们是软件开发经验的总结,能够帮助开发人员在设计阶段快速找到合适的解决方案,提高代码的可维护性、可扩展性和可复用性。设计模式主要分为三…...

FTPS、HTTPS、SMTPS以及WebSockets over TLS的概念及其应用场景
一、什么是FTPS? FTPS,英文全称File Transfer Protocol with support for Transport Layer Security (SSL/TLS),安全文件传输协议,是一种对常用的文件传输协议(FTP)添加传输层安全(TLS)和安全套接层(SSL)加密协议支持的扩展协议。…...
RK3568项目(七)--uboot系统之外设与PMIC详解
目录 一、引言 二、按键 ------>2.1、按键种类 ------------>2.1.1、RESET ------------>2.1.2、UPDATE ------------>2.1.3、PWRON 部分 ------------>2.1.4、RK809 PMIC ------------>2.1.5、ADC按键 ------------>2.1.6、ADC按键驱动 ------…...
Three.js进阶之粒子系统(一)
一些特定模糊现象,经常使用粒子系统模拟,如火焰、爆炸等。Three.js提供了多种粒子系统,下面介绍粒子系统 一、Sprite粒子系统 使用场景:下雨、下雪、烟花 ce使用代码: var materialnew THRESS.SpriteMaterial();//…...
【仿生机器人】刀剑神域——爱丽丝苏醒计划,需求文档
仿生机器人"爱丽丝"系统架构设计需求文档 一、硬件基础 已完成头部和颈部硬件搭建 25个舵机驱动表情系统 颈部旋转功能 眼部摄像头(视觉输入) 麦克风阵列(听觉输入) 颈部发声装置(语音输出)…...
小白的进阶之路系列之十四----人工智能从初步到精通pytorch综合运用的讲解第七部分
通过示例学习PyTorch 本教程通过独立的示例介绍PyTorch的基本概念。 PyTorch的核心提供了两个主要特性: 一个n维张量,类似于numpy,但可以在gpu上运行 用于构建和训练神经网络的自动微分 我们将使用一个三阶多项式来拟合问题 y = s i n ( x ) y=sin(x) y=sin(x),作为我们的…...
JavaScript性能优化实战大纲
性能优化的核心目标 降低页面加载时间,减少内存占用,提高代码执行效率,确保流畅的用户体验。 代码层面的优化 减少全局变量使用,避免内存泄漏 // 不好的实践 var globalVar I am global;// 好的实践 (function() {var localV…...

Python 解释器安装全攻略(适用于 Linux / Windows / macOS)
目录 一、Windows安装Python解释器1.1 下载并安装Python解释1.2 测试安装是否成功1.3 设置pip的国内镜像------永久配置 二、macOS安装Python解释器三、Linux下安装Python解释器3.1 Rocky8.10/Rocky9.5安装Python解释器3.2 Ubuntu2204/Ubuntu2404安装Python解释器3.3 设置pip的…...

Java多线程从入门到精通
一、基础概念 1.1 进程与线程 进程是指运行中的程序。 比如我们使用浏览器,需要启动这个程序,操作系统会给这个程序分配一定的资源(占用内存资源)。 线程是CPU调度的基本单位,每个线程执行的都是某一个进程的代码的某…...

【芯片仿真中的X值:隐藏的陷阱与应对之道】
在芯片设计的世界里,X值(不定态)就像一个潜伏的幽灵。它可能让仿真测试顺利通过,却在芯片流片后引发灾难性后果。本文将揭开X值的本质,探讨其危害,并分享高效调试与预防的实战经验。 一、X值的本质与致…...
C++ 变量和基本类型
1、变量的声明和定义 1.1、变量声明规定了变量的类型和名字。定义初次之外,还申请存储空间,也可能会为变量赋一个初始值。 如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显式地初始化变量: e…...
LeetCode第244题_最短单词距离II
LeetCode第244题:最短单词距离II 问题描述 设计一个类,接收一个单词数组 wordsDict,并实现一个方法,该方法能够计算两个不同单词在该数组中出现位置的最短距离。 你需要实现一个 WordDistance 类: WordDistance(String[] word…...
Linux 中替换文件中的某个字符串
如果你想在 Linux 中替换文件中的某个字符串,可以使用以下命令: 1. 基本替换(sed 命令) sed -i s/原字符串/新字符串/g 文件名示例:将 file.txt 中所有的 old_text 替换成 new_text sed -i s/old_text/new_text/g fi…...