前端问答:JavaScript 中的??和|| 有啥不同

77953d32b56944f3d46762097a757e33.png

在 JavaScript 开发中,很多小伙伴都会遇到一个场景,就是要给变量设置一个默认值,比如当变量没有有效值时,使用一个备用值。这个时候,可能有两个操作符会让你感到困惑:??(空值合并运算符)和 ||(逻辑或运算符)。一开始看,它们似乎都能达到相同的效果,但其实它们背后的逻辑完全不同,适用的场景也不一样。今天我们就来聊聊这两者的区别,帮你快速上手,避免掉坑!

"||" 是怎么工作的?—— 就像找备胎一样!

|| 就好像是在说:“如果这个不行,就换另一个。”它的具体作用是检查左边的值(第一个计划),如果左边这个值是 “假”(也就是不靠谱、不能用的意思),它就会去看右边的值(第二个计划),并返回右边的值。

举个例子来理解一下:

let result = value1 || value2;

这段代码就是在说:“如果 value1 能用,就用 value1;如果 value1 不行,那就用 value2 吧!”那问题来了,什么情况下 value1 会不行呢?

什么是 "假值"?

在 JavaScript 里,有一些特殊的值会被认为是“假”的,像这些:

  • false(假)

  • 0(零)

  • ""(空字符串)

  • null(表示空)

  • undefined(未定义)

  • NaN(非数字)

这些值都被认为是不能用的“假值”。如果你遇到这些值,|| 操作符就会帮你返回后面的备用计划。

举个栗子🌰:

let username = "" || "游客"; // 返回 "游客"
let score = 0 || 10;          // 返回 10

在上面的例子里,""(空字符串)和 0 都是“假值”,所以 JavaScript 会忽略它们,直接选择后面的“游客”和 10 作为返回值。

那什么时候用 "||" 呢?

|| 的最佳使用场景就是当你不确定一个值是否靠谱的时候,你可以为它准备一个备用值。就像生活中你遇到的两手准备:如果第一种方案失败了,立刻执行第二种。

比如你想让用户输入他们的名字,但如果用户没有输入名字,你就让系统自动叫他们“游客”。用 || 来实现这个需求简直再好不过了:

function greetUser(name) {let username = name || "游客";console.log(`你好, ${username}!`);
}greetUser("");  // 输出: 你好, 游客!
greetUser("Alice");  // 输出: 你好, Alice!

在这个例子里,如果用户没有输入名字(比如空字符串 ""),我们就用 || 返回一个默认值“游客”。但如果用户输入了名字(比如 “Alice”),我们就用这个名字打招呼。

JavaScript 中的"??"操作符:只关心空值,别搞混了!

JavaScript 里的??(空值合并运算符)看起来和我们之前聊过的||有点像,但它其实更“挑剔”!如果说||是遇到假值就找备胎,那么??只会在 nullundefined 出现时才出手救场。今天咱们就来深入了解一下这个 ECMAScript 2020 (ES11) 中的新工具。

"??" 是怎么工作的?—— 只处理“真正”的空值

?? 操作符的工作方式是:当左边的值是 nullundefined 时,才返回右边的备用值。像 0false"" 这些“假值”,在??眼里都是 有效值,它们不会触发备用计划。

语法很简单:

let result = value1 ?? value2;

意思是:如果 value1nullundefined,那就返回 value2;否则就直接用 value1

举个例子🌰:

let username = "" ?? "游客"; // 返回 ""
let score = 0 ?? 10;          // 返回 0

在这两个例子中,空字符串 ""0 虽然是“假值”,但因为它们不是 nullundefined?? 不会认为它们无效,所以直接返回它们本身。这样就避免了 || 操作符那种“误判”的情况——如果你真的想用 0"" 作为有效值,?? 就非常合适。

什么时候用"??"?

?? 非常适合在你 只想处理nullundefined 的场景下使用。比方说,你希望某个变量可以是 0false 这样的值,而不想让它们触发默认值。来看个小例子:

function getScore(score) {return score ?? 10;
}console.log(getScore(0));    // 输出: 0
console.log(getScore(null)); // 输出: 10

在这个例子里,score 可以是 0,也可以是 null。如果传入 0?? 不会把它当成空值,而是直接返回 0。但如果 scorenull,它就会返回默认值 10。这种行为对于某些场景非常有用,比如分数为 0 的时候你不希望它被误当成无效值。

??|| 的关键区别:用错容易踩坑哦!

在 JavaScript 里,??(空值合并运算符)和 ||(逻辑或运算符)都是用来设置默认值的利器,初学者可能觉得它们差不多,但其实它们的行为有很大不同。为了避免代码里的坑,我们必须清楚两者的使用场景和差异。

1. "Falsy" vs. "Nullish":谁才是真的空?

||:它的逻辑是,遇到任何“假值”(falsy)就会返回备用值。这些“假值”包括:

  • false

  • 0

  • ""(空字符串)

  • null

  • undefined

  • NaN(非数字)

只要值是这些“假值”,|| 就会触发备用值。

??:相比之下,?? 只关注 nullundefined。也就是说,像 0false"" 这些虽然看似“假”的值,但在 ?? 眼中是有效的,不会触发备用值。

2. 使用场景:该选谁?

  • 使用 ||:当你想对所有“假值”都提供一个备用方案时,比如 false0 或空字符串。这种情况下,|| 是你最好的选择。

  • 使用 ??:如果你只想处理 nullundefined,而对 0false 这些值保留,那么 ?? 更适合你。

3. 举例对比:看代码更直观

let value1 = 0 || 5;    // value1 是 5
let value2 = 0 ?? 5;    // value2 是 0let value3 = null || "默认值";  // value3 是 "默认值"
let value4 = null ?? "默认值";  // value4 是 "默认值"

在第一个例子中,value1 变成了 5,因为 0|| 认为是“假值”。而在 ?? 的情况下,value2 保持为 0,因为 0 并不是 nullundefined,所以不会触发备用值。

第二个例子里,null 在两种操作符中都触发了备用值,结果一样。

4. 潜在的 Bug:小心别踩坑!

误用 || 会导致一些你没料到的问题,特别是当 0false"" 是有效值时。来看个例子:

function getDiscountedPrice(price) {return price || 100;  // 这里会返回 100,即使 price 是 0
}console.log(getDiscountedPrice(0));  // 输出: 100(错误)

这里的逻辑会导致问题,因为 0 是一个有效的价格,但由于 || 把它当作“假值”,最终返回了备用值 100。解决方案就是用 ??,这样 0 就不会被误判了:

function getDiscountedPrice(price) {return price ?? 100;  // 这里会正确返回 0
}console.log(getDiscountedPrice(0));  // 输出: 0(正确)

5. 短路求值:谁先说了算?

||?? 都使用了 短路求值,意思是如果左边的值能决定结果,右边的值就不会被计算。但两者的判断标准不同——|| 会在遇到任意“假值”时短路,而 ?? 只会在 nullundefined 时短路。

6.总结:怎么选?

  • 如果你需要处理所有的“假值”(包括 0false""),就用 ||

  • 如果你只关心 nullundefined,而 0false 这些值也是有效输入,那就用 ??

结合 ||??:多重保险,让代码更健壮!

有时候,你可能会遇到更复杂的场景,既要处理 nullundefined,又需要对其他“假值”如 0false"" 做特殊处理。这种情况下,我们可以把 ||?? 结合起来,打造一个更加全面的“多重保险”逻辑。

为什么要同时用 ||??

?? 负责处理 null 和 **undefined**,而 || 可以处理 所有“假值”(如 0false、空字符串等)。有些情况下,你可能希望 nullundefined 返回默认值,而对于其他“假值”则使用不同的逻辑处理。

来看个例子:

let result = (value ?? defaultValue) || fallbackValue;

在这段代码中,我们做了两步处理:

1.value ?? defaultValue:首先,?? 检查 value 是否为 nullundefined。如果是,那么返回 defaultValue;如果不是,则直接返回 value。2. || fallbackValue:接下来,结果再经过 ||,如果这个结果是“假值”(例如 0false、空字符串等),就返回 fallbackValue

举个栗子🌰

假设你在处理一个分数系统,nullundefined 的时候要用默认分数,但同时如果分数是 0 也不能直接忽略,需要特殊处理。我们可以这样写:

function getFinalScore(score) {return (score ?? 50) || "分数无效";
}console.log(getFinalScore(null));  // 输出: 50(null 被 `??` 处理)
console.log(getFinalScore(0));     // 输出: "分数无效"(0 被 `||` 处理)
console.log(getFinalScore(80));    // 输出: 80(有效分数)
  • null 的情况scorenull 时,?? 返回默认值 50,|| 不会再触发。

  • 0 的情况score0 时,?? 不起作用,||0 视为“假值”,返回 "分数无效"。

  • 有效分数的情况score 是 80 时,直接返回 80。

什么时候使用这种组合?

这种组合特别适合需要处理复杂逻辑的场景,比如:

  • nullundefined 的时候,返回一个默认值;

  • 其他“假值”(如 0false)也需要单独处理,避免被误认为无效。

结束

在 JavaScript 开发中,??|| 绝对是处理默认值的利器,虽然它们看上去很像,但实际应用中却有明显区别。|| 会把很多值当作“假值”,包括 0false、空字符串等;而 ?? 只关心 nullundefined。因此,合理选择这两个运算符,能让你避免不必要的 Bug,尤其是在处理特殊值的时候。

那么问题来了,你在开发中遇到过 ||?? 这种场景吗?又是怎么处理的呢?欢迎在评论区分享你的开发经验或遇到的坑,咱们一起交流交流!

同时,别忘了关注「前端达人」,每天带你学习实用的前端开发技巧,让我们一起成长!

如果你觉得今天的内容对你有帮助,记得点个 在看分享 给身边的小伙伴哦!😊

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

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

相关文章

STM32 OLED

文章目录 前言一、OLED是什么?二、使用步骤1.复制 OLED.C .H文件1.1 遇到问题 2.统一风格3.主函数引用头文件3.1 oled.h 提供了什么函数 4.介绍显示一个字符的函数5. 显示十进制函数的讲解 三、使用注意事项3.1 配置符合自己的引脚3.2 花屏总结 前言 提示&#xff…

基于CNN+Transformer混合模型实现交通流量时序预测(PyTorch版)

前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对…

铰链+屏幕齐发力,告诉你 Mate XT 是如何让折痕变得“无存在感”

“折痕”是折叠手机永恒的话题,每一款折叠屏手机产品的问世,都逃不过对折痕的关注和讨论。 为什么会存在折痕? 材料在弯折的状态下会受到力的作用,在内部产生“压缩”的应力和“拉伸”的应力,这些应力集中在弯折的区…

Gromacs pdbtogro and grotopdb问题

这里,input.pdb 是您的输入 PDB 文件的名称,output.gro 是生成的 GRO 文件的名称。这个命令会将 PDB 文件转换为 GRO 格式,并生成一个包含模拟系统结构信息的 GRO 文件。 在执行此命令之前,确保您已经安装了 GROMACS 并设置了相应…

【ASE】第四课_高亮显示效果(手动切换)

今天我们一起来学习ASE插件,希望各位点个关注,一起跟随我的步伐 今天我们来学习高亮的效果。 思路: 1.添加纹理贴图和法线贴图,环境光遮挡贴图 2.添加高亮的参数,并设置 3.手搓一个边缘光,通过高亮参数调节 4.将模…

前端——js补充

一、数学对象 1.随机数 // 0-1 console.log(Math.random()); // 0-9 console.log(Math.random() * 9); // 6-13 console.log(Math.random() * (13 - 6) 6); //n-m Math.random() * (m - n) n 2.取整 // 向下取整 console.log(Math.floor(1.9));//1 // 向上取整 console.log(…

常用的10款图纸加密软件分享|2024年设计图纸怎么加密?赶紧收藏

在当今数字化时代,设计图纸作为企业核心资产之一,其安全性与保密性显得尤为重要。图纸一旦泄露,不仅可能导致知识产权的流失,还可能对企业造成重大经济损失,甚至影响其在行业内的竞争力。因此,图纸加密软件…

什么牌子的护眼台灯质量好?五款护眼台灯性价比高又好用

如今,市场上的护眼台灯琳琅满目,种类繁多。家长们为了孩子们的视力健康,都会精心挑选合适的台灯。什么牌子的护眼台灯质量好?然而,市面上仍存在一些质量不过关的产品,可能会出现频闪、线路短路、底盘过热、…

基于springboot+小程序的医院核酸检测服务管理系统(医院2)(源码+sql脚本+视频导入教程+文档)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于springboot小程序的医院核酸检测服务管理系统实现了管理员、用户管理、普通管理员、医护人员。 1、管理员实现了首页、用户管理、医护人员管理、普通管理员、通知公告管理、疫苗接种…

DnsDiag:一款针对DNS的故障排除和安全审计工具

关于DnsDiag DnsDiag是一款针对DNS的故障排除和安全审计工具,在该工具的帮助下,广大研究人员可以轻松检测DNS基础设施的安全性。 你是否曾怀疑过你的 ISP 是否劫持了你的 DNS 流量?你是否曾观察到 DNS 响应有任何异常行为?你是否…

SpringBoot集成-RocketMQ快速入门

1.MQ概述 MQ全称为Message Queue,即消息队列 ,是一种提供消息队列服务的中间件,也称为消息中间件,是一套提供了消息生 产、存储、消费全过程的软件系统,遵循FIFO原则。 1.1MQ常见产品 ActiveMQ ActiveMQ是使用Java语…

js列表数据时间排序和取唯一值

1.取唯一值[...new Set(array)] const array [1, 2, 3, 2, 4, 5, 3, 5]; // 使用Set去除重复元素 const uniarray [...new Set(array)]; console.log(uniarray); // 输出: [1, 2, 3, 4, 5] 2.排序 var u [1,3,2,5,4]; var uu u.sort(); console.log(uu); var u [1,3…

Commons-io工具包

FileUtils类(文件/文件夹相关) IOUtils类 Commons IO – 下载 Apache Commons IO 解压缩 将第一个jar包放入到项目的lib文件夹中 加入到项目之后,需要关联上,在关联上之后就可以打开看见里面写的文件了。

面试中考察栈和队列的经典算法题

💝💝💝如果你对顺序表的概念与理解还存在疑惑,欢迎观看我之前的作品👉【栈和列队详解】 上篇文章👉 【面试中顺序表常考的十大题目解析】 目录 💯前言 💯栈相关题目 ⭐有效的括号…

【Python|接口自动化测试】使用requests库发送HTTP请求

1.requests模块介绍 Python的requests模块是一个非常流行的第三方库,用于发送HTTP请求。它简化了与Web服务进行交互的过程,使得开发人员可以更方便地处理HTTP请求和响应。 本篇文章需要对HTTP和Python有一定的了解,只会解释关键性的操作 安…

javascript:监听浏览器页签切换

监听页面的可见性变化,在很多场景下非常实用,比如跟踪用户行为、节省资源、优化性能等。 1 代码示例 document.addEventListener("visibilitychange", () > {if (document.visibilityState "visible") {alert("当前页面已…

VUE 开发——Node.js学习(一)

一、认识Node.js Node.js是一个跨平台JavaScript运行环境,使开发者可以搭建服务器端的JavaScript应用程序 使用Node.js编写服务器端程序——编写数据接口、前端工程化; Node.js环境没有BOM和DOM; Node.js安装:下载node-v16.19…

聚观早报 | Redmi K80 Pro电池细节;vivo X200 Pro mini真机照

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 9月30日消息 Redmi K80 Pro电池细节 vivo X200 Pro mini真机照 广汽集团正制订深化改革方案 蔚来中国获新一轮增…

敢不敢动手?AI绘画+表情包制作,7步搞定超萌表情!

在这个信息爆炸的时代,表情已经成为我们日常沟通中不可或缺的一部分。然而,过去制作个性化表情包不仅耗时费力,还需要掌握复杂的设计软件,如AE、AI、(Adobe Illustrator )、PS。然而,随着AI绘画技术的兴起&…

一天学习开发一个APP!PDF转Word文档,Power Platform也能搞定

之前,给大家分享了微软Power Platform开发课程——手把手教你搭建二维码识别器,大家都很感兴趣。听说,很多小伙伴对于PDF转Word文档有困扰,这期我们继续为大家分享Power Platform的开发能力与技巧,怎么通过Power Platf…