0

0

什么是JS的空值合并操作?

幻夢星雲

幻夢星雲

发布时间:2025-08-30 14:27:01

|

692人浏览过

|

来源于php中文网

原创

空值合并操作符 ?? 在 JavaScript 中用于精确处理默认值,仅当左侧为 null 或 undefined 时返回右侧值,与 || 运算符不同,后者会将 0、''、false 等假值也视为“空”。?? 更适用于 0、false、空字符串为有效值的场景,如配置项、用户输入等,能避免 || 带来的意外覆盖。使用时需注意:?? 不能与 && 或 || 混合使用而无括号,否则会报语法错误,必须通过括号明确优先级。该操作符自 ES2020 引入,现代浏览器支持良好,旧环境可通过 Babel 转译确保兼容。

什么是js的空值合并操作?

JavaScript中的空值合并操作符

??
,在我看来,是一个相当优雅且实用的语法糖,它提供了一种更精确的方式来处理默认值。简单来说,它只会在左侧表达式为
null
undefined
时,才使用右侧的默认值。这和我们过去习惯的
||
运算符有着本质的区别,让代码在很多场景下变得更加清晰和可靠。

解决方案

空值合并操作符

??
(Nullish Coalescing Operator)是ES2020引入的一个新特性,它的核心功能是当左侧的操作数为
null
undefined
时,返回右侧的操作数;否则,返回左侧的操作数。这和逻辑或操作符
||
有着关键的不同。

举个例子,假设我们有一个配置对象,其中某个属性可能未定义,或者明确设置为

null
。我们希望为它提供一个默认值。

// 传统方式,使用 ||
const configA = { timeout: 0 };
const timeoutA = configA.timeout || 3000; // timeoutA 会变成 3000,因为 0 是一个 falsy 值

const configB = { timeout: null };
const timeoutB = configB.timeout || 3000; // timeoutB 会变成 3000

const configC = {};
const timeoutC = configC.timeout || 3000; // timeoutC 会变成 3000

console.log(timeoutA); // 3000
console.log(timeoutB); // 3000
console.log(timeoutC); // 3000

// 使用 ??
const configD = { timeout: 0 };
const timeoutD = configD.timeout ?? 3000; // timeoutD 依然是 0,因为 0 既不是 null 也不是 undefined

const configE = { timeout: null };
const timeoutE = configE.timeout ?? 3000; // timeoutE 会变成 3000

const configF = {};
const timeoutF = configF.timeout ?? 3000; // timeoutF 会变成 3000,因为 configF.timeout 是 undefined

console.log(timeoutD); // 0
console.log(timeoutE); // 3000
console.log(timeoutF); // 3000

从上面的例子可以看出,

??
运算符在处理
0
''
(空字符串)或
false
这些在
||
运算符看来是“假值”但实际上可能是有效值的情况下,表现出了它的独特优势。它只关心是不是
null
undefined
,这使得我们在为变量设置默认值时,能够更加精确地表达意图。

??
||
运算符有什么本质区别?

这真的是一个非常值得深挖的问题,因为这两个运算符看起来相似,但在实际应用中,它们对“空”的定义完全不同。我个人觉得,理解这个区别是掌握

??
关键。

||
逻辑或运算符,它会检查左侧操作数是否为“假值”(falsy value)。在 JavaScript 中,假值包括:
false
0
''
(空字符串)、
null
undefined
NaN
。只要左侧是这些值中的任何一个,
||
就会返回右侧的操作数。这在很多场景下非常方便,比如快速为变量提供一个“非空”的默认值。

但是,问题也随之而来。设想一下,如果

0
''
false
本身就是你想要保留的有效值呢?比如,一个用户配置项
timeout
设置为
0
,意味着“永不超时”;一个
userName
设置为空字符串
''
,意味着“匿名”;或者一个
isAdmin
布尔值设置为
false
,表示“不是管理员”。在这些情况下,如果使用
||
来提供默认值,那么
0
''
false
都会被误认为是“无效”或“空”,从而被默认值替代,这显然不是我们想要的。

??
空值合并操作符,它对“空”的定义要严格得多。它只关心左侧操作数是否是
null
undefined
。只有当左侧是这两者之一时,它才会返回右侧的操作数。这意味着,像
0
''
false
甚至是
NaN
,在
??
看来,它们都是“有值”的,都会被保留下来。这种精确性,在我看来,大大提升了代码的语义表达能力,减少了潜在的bug。

所以,本质区别在于:

  • ||
    关心的是“假值”(falsy values)。
  • ??
    关心的是“空值”(nullish values),即
    null
    undefined

理解这个差异,你就知道什么时候该用哪个了。

在实际开发中,何时应该优先选择
??
而不是
||

在实际开发中,我发现

??
运算符的引入,让很多过去需要额外判断才能写清楚的逻辑,变得简洁明了。我通常会在以下几种情况中优先选择
??

  1. 0
    false
    ''
    (空字符串)是有效且有意义的值时:
    这是
    ??
    最经典的用武之地。

    • 数值配置: 比如一个API请求的超时时间
      timeout
      ,如果设置为
      0
      ,可能意味着“不设置超时”或“立即返回”。
      const userSettings = {
          timeout: 0,
          retries: null
      };
      const actualTimeout = userSettings.timeout ?? 5000; // 得到 0,而不是 5000
      const actualRetries = userSettings.retries ?? 3;     // 得到 3
      console.log(`Timeout: ${actualTimeout}, Retries: ${actualRetries}`); // Timeout: 0, Retries: 3
    • 布尔标志: 一个
      isEnabled
      属性,如果明确设置为
      false
      ,就应该保持
      false
      ,而不是被默认值
      true
      覆盖。
      const featureConfig = {
          isEnabled: false,
          // showTips: undefined
      };
      const displayFeature = featureConfig.isEnabled ?? true; // 得到 false
      const showUserTips = featureConfig.showTips ?? true;   // 得到 true
      console.log(`Display Feature: ${displayFeature}, Show Tips: ${showUserTips}`); // Display Feature: false, Show Tips: true
    • 字符串处理: 用户名或描述字段,如果用户输入了空字符串,这本身可能就是一种有效状态,而不是未提供。
      const userData = {
          username: '',
          email: null
      };
      const displayUsername = userData.username ?? '匿名用户'; // 得到 ''
      const displayEmail = userData.email ?? '未提供';       // 得到 '未提供'
      console.log(`Username: "${displayUsername}", Email: "${displayEmail}"`); // Username: "", Email: "未提供"
  2. 维护数据类型和精确性: 当你从后端API获取数据时,如果某个字段可能返回

    null
    undefined
    ,但你希望其他非空值(包括
    0
    false
    )能够被正确地保留下来,
    ??
    就显得非常重要。它帮助你确保数据的完整性,避免了
    ||
    可能导致的类型转换或值丢失。

  3. 避免意外的副作用: 有时候,左侧表达式可能是一个函数调用,如果这个函数返回

    0
    false
    ,而你又不想它被默认值覆盖,
    ??
    是更安全的选择。

总而言之,只要你认为

0
false
''
应该被视为“有意义的值”而不是“空”,那么
??
就是你设置默认值时的首选。它让你的代码意图更加明确,也减少了因为“假值”判断带来的潜在逻辑错误。

??
运算符可以和
&&
||
混合使用吗?有哪些注意事项?

是的,

??
运算符可以和
&&
(逻辑与)或
||
(逻辑或)混合使用,但这里有一个非常重要的“坑”需要注意,否则会遇到语法错误。

JavaScript为了避免操作符优先级可能导致的歧义,不允许

??
直接与
&&
||
在同一个表达式中不加括号地混合使用。
如果你尝试这样做,JavaScript 会抛出一个
SyntaxError

手机在线人工冲值
手机在线人工冲值

说明:我不知道这个系统还能用到什么地方!他的运作方式是这样的,客户在其他地方比如掏宝购买了 你得卡,然后在你的网站进行冲值,你得有人登陆并看着后台,如果有人冲值,就会刷出记录,手工冲值完毕后,你得点击 [冲值完毕],客户的页面 就会返回 冲值信息!安装:上传所有文件,倒入(sql.txt)mysql数据库,使用myphpadminphplib 777phplib/sys.php 777phplib

下载

比如,这样的写法是会报错的:

// 这会抛出 SyntaxError
// const result = someValue ?? anotherValue || defaultValue;
// const result = someValue ?? anotherValue && defaultValue;

这是因为

??
的优先级介于
&&
||
之间。为了强制你明确意图,JS 引擎要求你必须使用括号来明确分组。

正确的使用方式是使用括号来明确操作符的执行顺序:

  1. 结合

    ||
    如果你想先执行
    ||
    ,再用
    ??
    提供最终的默认值:

    const userPref = null;
    const defaultSetting = 'default';
    const finalValue = (userPref || 'fallback') ?? defaultSetting;
    // 解释:userPref || 'fallback' -> null || 'fallback' -> 'fallback'
    // 'fallback' ?? defaultSetting -> 'fallback'
    console.log(finalValue); // 'fallback'
    
    const anotherPref = 0;
    const finalValue2 = (anotherPref || 'fallback') ?? defaultSetting;
    // 解释:anotherPref || 'fallback' -> 0 || 'fallback' -> 'fallback'
    // 'fallback' ?? defaultSetting -> 'fallback'
    console.log(finalValue2); // 'fallback'

    如果你想先用

    ??
    处理空值,然后整个表达式再与
    ||
    结合:

    const userPrefA = undefined;
    const userPrefB = null;
    const userPrefC = 0;
    const result = (userPrefA ?? userPrefB) || userPrefC;
    // 解释:userPrefA ?? userPrefB -> undefined ?? null -> null
    // null || userPrefC -> null || 0 -> 0
    console.log(result); // 0
  2. 结合

    &&
    如果你想先执行
    &&
    ,再用
    ??
    提供默认值:

    const condition = true;
    const value = null;
    const finalResult = (condition && value) ?? 'default';
    // 解释:condition && value -> true && null -> null
    // null ?? 'default' -> 'default'
    console.log(finalResult); // 'default'
    
    const condition2 = false;
    const value2 = 'data';
    const finalResult2 = (condition2 && value2) ?? 'default';
    // 解释:condition2 && value2 -> false && 'data' -> false
    // false ?? 'default' -> false
    console.log(finalResult2); // false

    如果你想先用

    ??
    处理空值,然后整个表达式再与
    &&
    结合:

    const a = undefined;
    const b = 'hello';
    const c = 'world';
    const result = (a ?? b) && c;
    // 解释:a ?? b -> undefined ?? 'hello' -> 'hello'
    // 'hello' && c -> 'hello' && 'world' -> 'world'
    console.log(result); // 'world'

总结注意事项:

  • 必须使用括号: 这是最重要的规则。当你需要在同一个表达式中同时使用
    ??
    &&
    ||
    时,请务必使用括号来明确你想要的操作顺序。
  • 理解优先级: 虽然强制使用括号避免了优先级问题,但了解
    ??
    的优先级低于
    &&
    ||
    仍然有助于你更好地设计表达式。
  • 清晰意图: 引入
    ??
    的目的就是为了更清晰地表达“空值”的概念。在混合使用时,也要确保你的代码意图依然清晰,避免过度复杂的表达式。如果一个表达式变得过于复杂,可以考虑将其拆分成多个步骤或使用临时变量。

??
运算符的浏览器兼容性和Polyfill方案是怎样的?

??
运算符是 ECMAScript 2020 (ES2020) 标准中引入的特性,这意味着它在较新的 JavaScript 环境中才能直接使用。

浏览器兼容性: 目前,主流的现代浏览器对

??
运算符的支持都非常好,包括:

  • Chrome (从 80 版本开始)
  • Firefox (从 72 版本开始)
  • Edge (从 80 版本开始)
  • Safari (从 13.1 版本开始)
  • Opera (从 67 版本开始)

你可以访问像 caniuse.com 这样的网站来查看最新的兼容性信息。对于绝大多数桌面和移动端用户来说,现在使用

??
已经不是什么大问题了。

Polyfill 方案: 虽然现代浏览器支持良好,但如果你需要支持一些老旧的浏览器环境(例如,一些企业内部应用可能还在使用旧版IE,或者某些嵌入式浏览器),那么你就需要考虑 Polyfill 或转译(Transpilation)方案。

通常,我们不会直接为

??
运算符编写 Polyfill 代码,因为它是一个语法特性,而不是一个全局对象或方法。最常见的做法是使用 Babel 这样的 JavaScript 编译器来将 ES2020+ 的语法转译成 ES5 或其他目标环境支持的语法。

当你使用 Babel 时,配合

@babel/preset-env
预设,它会自动检测你的目标浏览器环境,并将
??
这样的新语法转换为等效的旧语法。

例如,

a ?? b
可能会被转译成类似这样的形式:

var a = someValue;
var b = defaultValue;
var result = (a !== null && a !== undefined) ? a : b;

或者更简洁的:

var result = (someValue == null) ? defaultValue : someValue;

(注意这里的

== null
会同时检查
null
undefined
,这是 JS 的一个特性。)

如何配置 Babel: 如果你正在使用 Webpack、Rollup 或 Parcel 等构建工具,你通常会在 Babel 的配置文件(如

.babelrc
babel.config.js
)中配置
@babel/preset-env

一个简单的

babel.config.js
示例:

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          edge: '17',
          firefox: '60',
          chrome: '67',
          safari: '11.1',
          // 你可以根据你的项目需求指定支持的浏览器版本
        },
        useBuiltIns: 'usage', // 如果需要,也可以配置polyfill
        corejs: 3,
      },
    ],
  ],
};

通过这样的配置,Babel 会自动处理

??
这样的语法,确保你的代码在目标环境中也能正常运行。

在我看来,对于大多数现代前端项目,直接使用

??
已经是一个非常安全且推荐的做法。如果你的项目确实有兼容老旧浏览器的需求,那么通过构建工具和 Babel 进行转译是标准且高效的解决方案,通常不需要手动编写 Polyfill。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
chrome什么意思
chrome什么意思

chrome是浏览器的意思,由Google开发的网络浏览器,它在2008年首次发布,并迅速成为全球最受欢迎的浏览器之一。本专题为大家提供chrome相关的文章、下载、课程内容,供大家免费下载体验。

864

2023.08.11

chrome无法加载插件怎么办
chrome无法加载插件怎么办

chrome无法加载插件可以通过检查插件是否已正确安装、禁用和启用插件、清除插件缓存、更新浏览器和插件、检查网络连接和尝试在隐身模式下加载插件方法解决。更多关于chrome相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

752

2023.11.06

edge是什么浏览器
edge是什么浏览器

Edge是一款由Microsoft开发的网页浏览器,是Windows 10操作系统中默认的浏览器,其目标是提供更快、更安全、更现代化的浏览器体验。本专题为大家提供edge浏览器相关的文章、下载、课程内容,供大家免费下载体验。

1454

2023.08.21

IE浏览器自动跳转EDGE如何恢复
IE浏览器自动跳转EDGE如何恢复

ie浏览器自动跳转edge的解决办法:1、更改默认浏览器设置;2、阻止edge浏览器的自动跳转;3、更改超链接的默认打开方式;4、禁用“快速网页查看器”;5、卸载edge浏览器;6、检查第三方插件或应用程序等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

383

2024.03.05

如何解决Edge打开但没有标题的问题
如何解决Edge打开但没有标题的问题

若 Microsoft Edge 浏览器打开后无标题(窗口空白或标题栏缺失),可尝试以下方法解决: 重启 Edge:关闭所有窗口,重新启动浏览器。 重置窗口布局:右击任务栏 Edge 图标 → 选择「最大化」或「还原」。 禁用扩展:进入 edge://extensions 临时关闭插件测试。 重置浏览器设置:前往 edge://settings/reset 恢复默认配置。 更新或重装 Edge:检查最新版本,或通过控制面板修复

950

2025.04.24

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

310

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

237

2023.09.22

go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

30

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.7万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号