JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题
目录
JavaScript双问号操作符(??)详解,解决使用||时因类型转换带来的问题
一、双问号操作符??的基础用法
1、传统方式的痛点
2、双问号操作符??的精确判断
3、双问号操作符??与逻辑或操作符||的对比
二、复杂场景下的空值处理
1、深层嵌套对象的默认值
2、函数参数的默认值陷阱
3、多条件回退策略
三、实战案例解析
1、Vue组件中的Prop处理
2、表单验证
四、双问号操作符的性能优势
五、结语
作者:watermelo37
CSDN万粉博主、华为云云享专家、阿里云专家博主、腾讯云、支付宝合作作者,全平台博客昵称watermelo37。
一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。
---------------------------------------------------------------------
温柔地对待温柔的人,包容的三观就是最大的温柔。
---------------------------------------------------------------------
JavaScript双问号操作符(??)详解,解决使用||时因类型转换带来的问题
在现代JavaScript开发中,处理变量默认值是一个常见但容易引发bug的操作。很多开发者可能都遇到过这样的问题:使用||设置默认值时,意外覆盖了0、''等合法值。这时候,ES2020引入的双问号操作符(??)就能完美解决这类问题。本文将带您全面掌握这个操作符的使用场景和高级技巧。
一、双问号操作符??的基础用法
1、传统方式的痛点
const count = 0;
const result = count || 10; // 得到10,但0可能是有效值
使用||时,会把所有假值 (falsy values)视为无效值,包括:0、''、false、NaN、null、undefined。这在处理数字表单、开关状态等场景时会引发问题。
以上述案例来说,我想要count被赋值的情况下就使用count的值,要是没有被赋值就使用默认值10,但是当count被初始化并赋值为0的时候,逻辑或操作符||依然会认为是无效值,并将result赋值为10,这显然和我预期的结果相悖。这是因为JavaScript是一门弱类型语言,会进行强制类型转换。
2、双问号操作符??的精确判断
同样还是这个例子:
const count = 0;
const result = count ?? 10; // 得到0,完美保留有效值
此时result的结果就是10,因为??操作符只对null和undefined这两个原始值进行判断,其他假值都会被保留。这种特性使其特别适合处理以下场景:
- 表单输入值(允许0或空字符串)
- 布尔类型配置项
- 数字类型参数(允许0)
3、双问号操作符??与逻辑或操作符||的对比
特性 | ?? 操作符 | || 操作符 |
---|---|---|
触发条件 | 仅 null/undefined | 所有假值 |
适用场景 | 精准空值判断 | 快速默认值设置 |
处理 0 和 '' | 保留有效值 | 覆盖为默认值 |
处理 false | 保留布尔值 | 覆盖为默认值 |
二、复杂场景下的空值处理
1、深层嵌套对象的默认值
结合可选链操作符(?.),可以安全地处理多层嵌套对象的属性访问。
const config = {api: {v1: {endpoint: ''}}
};// 传统写法(需要逐层判断)
const endpoint = config.api?.v1?.endpoint || 'default';// 使用??的改进写法
const endpoint = config.api?.v1?.endpoint ?? 'default';
2、函数参数的默认值陷阱
当函数参数需要接收布尔值时,使用??可以避免意外覆盖用户传入的false值。
function createPost(data) {// 错误写法:会覆盖有效布尔值const isPublic = data.isPublic || true;// 正确写法:仅处理null/undefinedconst isPublic = data.isPublic ?? true;
}
3、多条件回退策略
通过链式使用??,可以实现多层级的配置回退机制,这种模式在读取环境变量时特别实用。
const theme = userConfig.theme ?? systemConfig.theme ?? process.env.THEME ?? 'light';
三、实战案例解析
1、Vue组件中的Prop处理
如果disabled接收的值为false,如果使用逻辑或操作符,就会被认为是无效值,从而使用默认的true值。如果使用双问号操作符就可以避免这种情况。
<template><input :disabled="isDisabled" />
</template><script>
export default {props: {disabled: {type: Boolean,default: undefined}},computed: {isDisabled() {return this.disabled ?? true;}}
}
</script>
2、表单验证
就算你不允许用户输入空格,起码要允许用户输入0和引号吧?如果使用逻辑或操作符,根本无法通过表单验证,使用双问号操作符就可以避免这种情况。
function validateForm(formData) {const errors = [];if (formData.username?.trim() ?? false) {errors.push('用户名不能为空');}if (formData.age ?? false) {errors.push('年龄必须填写');}return errors;
}
四、双问号操作符的性能优势
实际测试显示,??在性能上与||基本持平,但在处理复杂对象时更具优势。这是因为双问号操作符只检查null和undefined,比||操作符的类型转换操作更高效。
当然,这部分差异很小,更多的作用是展示开发者的思维能力。
// 测试环境:Chrome 112,100万次运算
console.time('||');
for (let i = 0; i < 1000000; i++) null || 10;
console.timeEnd('||'); // 2.1msconsole.time('??');
for (let i = 0; i < 1000000; i++) null ?? 10;
console.timeEnd('??'); // 1.8ms
五、结语
双问号操作符(??)这个看似简单的语法糖,实则蕴含着提升代码健壮性的强大能力。在实际项目中,建议结合TypeScript的严格空值检查,构建更可靠的类型安全体系。
只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
其他热门文章,请关注:
极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图
你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解
DeepSeek:全栈开发者视角下的AI革命者
通过array.filter()实现数组的数据筛选、数据清洗和链式调用
通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能
TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急
通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
干货含源码!如何用Java后端操作Docker(命令行篇)
相关文章:
JavaScript双问号操作符(??)详解,解决使用 || 时因类型转换带来的问题
目录 JavaScript双问号操作符(??)详解,解决使用||时因类型转换带来的问题 一、双问号操作符??的基础用法 1、传统方式的痛点 2、双问号操作符??的精确判断 3、双问号操作符??与逻辑或操作符||的对比 二、复杂场景下的空值处理 …...
Go语言从零构建SQL数据库(5)-Pratt解析算法:SQL表达式解析的核心引擎
Pratt解析算法:SQL表达式解析的核心引擎 1. 算法概述与工作原理 Pratt解析算法(自顶向下运算符优先级解析)是一种优雅的表达式解析方法,特别适合处理具有不同优先级运算符的复杂表达式。在我们的SQL解析器中,它负责解…...
数字政府与电子政务综合分析报告
数字政府与电子政务综合分析报告 一、引言 随着信息技术的飞速发展,数字政府和电子政务成为全球公共管理领域的重要趋势。数字政府和电子政务的建设不仅是提升政府治理能力的必然选择,也是推动国家治理现代化的重要途径。本文将对数字政府和电子政务进…...
服务器虚拟化技术深度解析:医药流通行业IT架构优化指南
一、服务器虚拟化的定义与原理 (一)技术定义:从物理到虚拟的资源重构 服务器虚拟化是通过软件层(Hypervisor)将物理服务器的CPU、内存、存储、网络等硬件资源抽象为逻辑资源池,分割成多个相互隔离的虚拟机…...
QT ARM 开发环境搭建
搭建 QT ARM 开发环境主要包括主机环境配置、交叉编译工具链安装、QT 库交叉编译和 QT Creator 配置几个步骤。以下是详细流程: 一. 主机环境准备 系统要求 推荐 Ubuntu 18.04/20.04 LTS 或更高版本 至少 50GB 可用磁盘空间 8GB 以上内存 安装基础依赖 sudo apt update sud…...
【设计模式】外观模式
简介 想象你要在家里看电影,需要做以下操作: 打开电视启动音响调暗灯光关闭窗帘 如果每次都要手动操作这些步骤会很麻烦。外观模式可以帮你将这些步骤封装成一个统一的接口,比如“一键观影模式”,你只需按一个按钮,…...
[特殊字符] 驱动开发硬核特训 · Day 5 - 深入解析 Platform Driver 驱动框架
主题:深入解析 Platform Driver 驱动框架 —— 从架构设计到工程实战 平台驱动(platform driver)是 Linux 内核中应用最广泛的一种设备驱动框架。它用于管理那些不依赖总线枚举机制的固定外设,如 GPIO 控制器、I2C 控制器、SPI 控…...
创意 Python 爱心代码
在编程的世界里,Python 以其简洁易用和丰富的库而备受喜爱。用 Python 编写爱心代码,不仅能展现编程的魅力,还能传递温暖与爱意。今天就来分享几种创意 Python 爱心代码。 一、基于turtle库绘制爱心 turtle库是 Python 内置的图形库&#x…...
【群晖】挂载小雅alist到AList网盘中
群晖开启远程 在命令行远程到主机 ssh 用户名主机名终端中执行下方命令创建一个在AList中挂载小雅所需要的token: docker exec -i xiaoya sqlite3 data/data.db <<EOF select value from x_setting_items where key "token"; EOF 如果报权限错误…...
嵌入式C语言11(宏/程序的编译过程)
宏 ⦁ 基本概念 C语言中可以利用宏定义实现文本的快速替换,注意:宏定义是单纯的文本替换,不检查语法是否合法。 C语言标准中提供了很多的预处理指令,比如#include、#pragma…以#开头的都属于预处理指令。 预处理指令指的是在…...
城电科技 | 太阳能花怎么选择?光伏太阳花的应用场景在哪里?
在当下追求绿色能源的时代,珠海城电科技的太阳能花逐渐走进人们的视野。那么,太阳能花究竟是什么呢?太阳能花属于光伏发电应用的一种,巧妙地利用太阳能进行发电。它还有着光伏太阳花、光伏发电花、光伏智慧花等别称。 城电科技-光…...
[C++面试] C++中各类括号的差异:[]、{}、<>、()
括号类型典型场景编译期/运行时安全性考量()函数调用、运算优先级两者注意强制转换风险[]数组访问、Lambda捕获运行时主导防止越界访问{}统一初始化、聚合类型编译期检查阻止隐式窄化转换<>模板实例化、元编程编译期注意模板展开爆炸问题 int x{5}; int x(5);有什么区别…...
Qt 入门 3 之对话框 QDialog(1)
Qt 入门 3 之对话框 QDialog 本文从以下几点分开讲述: - 对话框的基本原理介绍 - 两种不同类型的对话框 - 一个由多个窗口组成并且窗口间可以相互切换的程序 1.模态和非模态对话框 QDialog 类是所有对话框窗口类的基类。对话框窗口是一个经常用来完成短小任务或者…...
Python设计模式:组合模式
1. 什么是组合模式 组合模式(Composite Pattern)是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次关系。组合模式使得客户端对单个对象和组合对象的使用具有一致性。换句话说,组合模式可以让客户端以相…...
第九天 - psutil系统监控库 - 资源监控仪表盘 - 练习:实时CPU/Memory监控
使用Python打造实时资源监控仪表盘(psutilFastAPI) 一、为什么要学习系统监控? 在软件开发中,系统资源监控是每个开发者都需要掌握的重要技能。无论是排查性能瓶颈、优化程序效率,还是确保服务稳定性,实时…...
Spring Boot内嵌服务器全解析:Tomcat vs Jetty vs Undertow 选型指南
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 引言 在Spring Boot应用中,内嵌服务器的选择直接影响应用的性能、资源占用和扩展性。尽管Tomcat作为默认选项被广泛使用,Jetty和Unde…...
【嵌入式学习6】多任务版TCP服务器
目录 如何实现: 客户端1.0版本: 服务端: 客户端2.0版本: thread.join() 是一个线程同步方法,用于主线程等待子线程完成。当你调用 thread.join() 时,主线程会阻塞,直到调用 join() 的子线程…...
抖音直播位置与IP属地不同?如何实现
抖音作为头部平台吸引了大量主播和观众。然而,许多用户发现一个令人困惑的现象:直播间显示的位置信息与账号IP属地不一致。本文将深入分析这一现象背后的原因,探讨可能带来的影响,并提供实用的解决方案。 一、抖音直播显示的位置与…...
Scala(六)
本节课学习了数组、列表、Set集合、Map集合、元组、集合中常用的函数等等。 数组包括可变数组、不可变数组,学习了如何定义和创建数组、可变数组和不可变数组之间的转换、多维数组、数组遍历 列表学习了如何添加元素、合并集合、如何访问元素、遍历列表 Set集合学…...
Android 11.0 framework系统首次开机添加锁屏壁纸的功能
1.前言 在11.0的系统rom定制化开发中,在某些时候需要默认设置锁屏壁纸功能,而系统中没有在 framework/base下没有单独的默认锁屏壁纸的图片替换,默认就是锁屏壁纸和主屏幕壁纸 都是同一张壁纸,所以就需要添加接口来实现设置默认锁屏壁纸的功能 2.framework系统首次开机添…...
Scala数组
数组 - 可变数组:以 ArrayBuffer 创建,可灵活增删改元素 ,如 ArrayBuffer(1, 2, 3) ,并通过 append 等方法操作。 - 不可变数组:由 Array 构建,创建后元素不可变,可借助 toBuffer 等方法转换为…...
Win11 24H2用户个性化设置OOBE跳过微软账户使用本地账户方法
目前Win11已经更新到24H2版本,经过小编测试,已经有两种方法失效了,分别如下。 1.shiftFnF10,oobe \bypassnro 2.微软账户注册界面,输入特定邮件地址和随机密码,例如nothankyou.com、exampleexample.com等…...
遍历集合list工具
文章目录 1.遍历集合list,返回第一个匹配的对象/不匹配返回null:2.集合list排序3.遍历list对象,返回匹配的集合4.从 dbRepeaters 列表中筛选出所有 repeaterId 在 repeaterIds 数组中的 Repeater 对象,并将这些对象收集到一个新的…...
基于 SmartX 原生容灾能力构建简单经济的容灾方案:5 大场景与 4 例实践合集
不少企业都基于虚拟化/超融合架构支持多种核心应用系统与数据库。这些场景不仅涉及多种类型的工作负载,在数据可靠性层面也需要不同级别的保护策略,一些用户还面临灾备演练、集中容灾等更多样的容灾需求,因此,构建全面可靠、易用高…...
说一下分布式组件时钟一致性的解决方案
为什么需要时钟一致性? 在分布式系统中,时钟一致性是确保各节点时间同步的关键问题。 时钟不同步可能导致日志混乱、事务顺序错误、数据不一致等问题 1. 物理时钟同步 基础方案:NTP(网络时间协议) 原理:…...
aws s3api 常用命令
AWS S3API 是 Amazon Web Services(AWS)提供的用于与简单存储服务(S3)进行交互的命令行工具,以下是一些常用命令: 桶操作 创建桶 aws s3api create-bucket --bucket <bucket-name> --region <r…...
006 ElementUI
https://element.eleme.cn/#/zh-CN ElementUI是组件库,网站快速成型工具 npm i element-ui2.12.0在 main.js 中写入以下内容: import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; Vue.use(ElementUI);...
el-select组件与el-tree组件结合实现下拉选择树型结构框
下拉选择树型结构框 实现效果图组件完整代码 实现效果图 组件完整代码 <template><div class"tree-con"><el-selectv-model"value"placeholder"请选择"class"bs-select"ref"select"><el-optionv-for&…...
windows系统更新nvidia 驱动, 并安装pytorch
windows系统更新nvidia 驱动, 并安装pytorch 1.更新前nvidia-smi 显示版本比较久 2.方法一:通过NVIDIA GeForce Experience自动更新 NVIDIA GeForce Experience是NVIDIA官方提供的一款软件,它不仅可以帮助用户优化游戏设置,还能…...
如何深刻理解Reactor和Proactor
前言: 网络框架的设计离不开 I/O 线程模型,线程模型的优劣直接决定了系统的吞吐量、可扩展性、安全性等。目前主流的网络框架,在网络 IO 处理层面几乎都采用了I/O 多路复用方案(又以epoll为主),这是服务端应对高并发的性能利器。 …...
如何使用WRF-Hydro GIS工具,生成运行WRF-Hydro模型的Domain文件,包括流域、地形、河网、湖泊等
WRF-Hydro模型作为一个集成了大气和水文过程的模型,具有一些挑战性的难点,包括: 复杂的耦合过程:WRF-Hydro模型需要同时考虑大气和水文过程的相互作用,包括降水、蒸发、径流等一系列过程的耦合,这使得模型的…...
adb devices报错 ADB server didn‘t ACK
ubuntu下连接手机首次使用adb devices 报错ADB server didn’t ACK adb devices * daemon not running; starting now at tcp:5037 ADB server didnt ACK Full server startup log: /tmp/adb.1000.log Server had pid: 52986 --- adb starting (pid 52986) --- 04-03 17:23:23…...
机器学习——决策树
1.什么要学习决策树? 处处都是选择,并且到处都是岔路口。比如你发现某只股票几天时间内涨了很多,如果是你,你会买进吗?如果买进了,你就得承担后果,要么会大赚一笔,要么会血本无归。总之,用算法替代主观判断,避免情绪化投资决策。 …...
zk源码—2.通信协议和客户端原理二
大纲 1.ZooKeeper如何进行序列化 2.深入分析Jute的底层实现原理 3.ZooKeeper的网络通信协议详解 4.客户端的核心组件和初始化过程 5.客户端核心组件HostProvider 6.客户端核心组件ClientCnxn 7.客户端工作原理之会话创建过程 6.客户端核心组件ClientCnxn (1)客户端核心…...
Python设计模式:构建模式
1. 什么是构建模式 构建模式(Builder Pattern)是一种创建型设计模式,它允许使用多个简单的对象一步步构建一个复杂的对象。构建模式通过将构建过程与表示分离,使得同样的构建过程可以创建不同的表示。换句话说,构建模…...
C++类间的 “接力棒“ 传递:继承(下)
文章目录 5. 继承与友元6.继承与静态成员7.菱形继承8.继承和组合希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力! 本篇接着补充继承方面的内容,同时本篇的菱形继承尤为重要 5. 继承与友元 class Student; class Person { public:fri…...
C++11QT复习 (十六)
文章目录 Day11 移动语义回顾一、移动语义基础概念二、自定义 String 类的移动语义实现输出运算符重载: 三、测试函数:验证移动与拷贝行为四、左值与右值的补充说明右值引用作为函数返回值 五、知识总结如何区分左值与右值? 六、附加说明&…...
Redis客户端命令到服务器底层对象机制的完整流程?什么是Redis对象机制?为什么要有Redis对象机制?
Redis客户端命令到服务器底层对象机制的完整流程 客户端 → RESP协议封装 → TCP传输 → 服务器事件循环 → 协议解析 → 命令表查找 → 对象机制 → 动态编码 → 数据结构操作 → 响应编码 → 网络回传 Redis客户端命令到服务器底层对象机制的完整流程可分为协议封装、命令解…...
鸿蒙NEXT开发节流、防抖工具类(ArkTs)
import { CacheUtil } from ./CacheUtil; import { DateUtil } from ./DateUtil;/*** 节流、防抖工具类(用于点击事件,防止按钮被重复点击)** author 鸿蒙布道师* since 2025/04/07*/ export class ClickUtil {private static throttleTimeou…...
Qt程序 Windows打包
目的 运行Qt的程序,遇上如下问题: 显然是少很多Qt库,那就把Qt库放到这里,Qt提供这一个命令windeployqt.exe. windeployqt windeployqt是Qt框架提供的一个工具,主要用于自动打包Windows平台上的Qt应用程序及其依赖项…...
2025-04-07(DS复习):Databricks DLT 详解
Databricks Delta Live Tables (DLT) 详解 Delta Live Tables (DLT) 是 Databricks 提供的一个智能框架,用于构建可靠、可扩展的数据处理管道。它简化了ETL(提取、转换、加载)和ELT(提取、加载、转换)流程的开发和管理,特别适合在数据湖house架构中实现…...
音视频入门基础:RTCP专题(3)——RTCP协议简介(中)
本文接着《音视频入门基础:RTCP专题(2)——RTCP协议简介(上)》,继续对RTCP协议进行简介。本文的一级标题从“九”开始。 九、Sender and Receiver Reports 本段内容对应《RFC 3550》的第6.4节。根据《RFC …...
嵌入式工程师多线程编程(二)生产者-消费者模式
生产者-消费者模式详解:多线程编程的核心范式 生产者-消费者模式(Producer-Consumer Pattern)是多线程编程中最经典的设计模式之一,它通过解耦生产者和消费者的工作流程,实现了线程间的高效协作与资源管理。本文将深入剖析这一模式的原理、实…...
秒杀系统的性能优化
秒杀任务总体QPS预期是每秒几十万,对tomcat、redis、JVM参数进行优化。 tomcat线程数 4核8G的机器,一般就是开200-300个工作线程,这是个经验值。每秒一个线程处理3-5个请求,200多个线程的QPS可以达到1000左右。线程不能太多&…...
MySQL学习笔记集--索引
索引 索引是数据库中用于提高查询效率的一种数据结构。 它类似于书籍的目录,通过索引可以快速定位到表中的特定行,而无需扫描整个表。 索引的类型 主键索引(Primary Key Index) 自动创建,用于唯一标识表中的每一行。…...
深入理解重排(Reflow)与重绘(Repaint),写出高性能 CSS 动画
在前端开发中,CSS 动画是提升用户体验的重要手段,但很多开发者在使用动画时并不了解浏览器背后的渲染机制,导致动画卡顿甚至影响整体性能。本文将带你深入理解 CSS 中的两大核心概念 —— 重排(Reflow) 与 重绘&#x…...
Elasticsearch 从入门到实战:文档聚合操作及总结
四、文档操作:数据的增删改查 4.1 添加文档 文档(Document)是索引中的最小数据单元,使用 POST 或 PUT 添加: json POST /products/_doc/1 { "name": "华为Mate50 Pro", "price": 6…...
前缀和和差分笔记
前缀和和差分笔记 一维前缀和 示意图如下: 代码: **核心公式:sum[i]sum[i-1]a[i];(计算前缀和的)**#include<bits/stdc.h> using namespace std; const int N10000; #define ll long long int a[N],sum[N]; i…...
SSRF漏洞利用的小点总结和实战演练
含义理解: SSRF(Server-Side Request Forgery,服务器请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞,一般情况下,SSRF攻击的目标是外网无法访问的内网系统。 攻击者通过篡改URL…...
IAR推动嵌入式开发:云就绪、可扩展的CI/CD和可持续自动化
全球领先的嵌入式系统开发软件解决方案供应商IAR正式发布全新云就绪平台,为嵌入式开发团队提供企业级的可扩展性、安全性和自动化能力。该平台于在德国纽伦堡举办的embedded world 2025展会上正式亮相,标志着将现代DevSecOps工作流集成到嵌入式软件开发中…...