讲师中心 微信公众号
AI工具推荐 视频效率加速

JavaScript如何用空值合并运算符设置默认值

小静君_3855

小静君_3855

发布时间:2025-07-10 23:02:02

|

967人浏览过

|

来源于php中文网

原创

javascript的空值合并运算符(??)与逻辑或(||)的核心差异在于判断“空值”的标准不同。1. ?? 运算符仅当左侧为 null 或 undefined 时才返回右侧操作数,保留 0、false 和 '' 等有效值;2. || 运算符基于“假值”判断,遇到 0、false、''、null、undefined 或 nan 都会返回右侧操作数。因此在需要区分有效假值和真正缺失值的场景,应优先使用 ?? 来避免误替换有效数据。

JavaScript如何用空值合并运算符设置默认值

JavaScript的空值合并运算符(??)提供了一种非常精确的方式来为变量设置默认值,它只在左侧操作数为null或undefined时才生效,这与传统的逻辑或运算符(||)处理所有“假值”的逻辑有本质区别,让开发者在需要区分0、空字符串或false这些有效值时,能更安全地提供备选方案。

JavaScript如何用空值合并运算符设置默认值

解决方案

在使用JavaScript处理数据或配置时,我们经常需要为可能缺失的值设定一个默认值。过去,很多人习惯用逻辑或运算符 || 来做这件事,比如 const value = input || defaultValue;。这在很多情况下确实管用,但它有个“副作用”,就是当 input 是 0、false 或 '' (空字符串)时,|| 也会把它当作“假值”,从而返回 defaultValue。

对我来说,这简直是个让人头疼的细节,因为在实际业务里,0 可能是库存数量,false 可能是某个开关状态,'' 可能是用户刻意留空的备注。这些都是有意义的“值”,不应该被简单地替换掉。

立即学习“Java免费学习笔记(深入)”;

JavaScript如何用空值合并运算符设置默认值

空值合并运算符 ?? 就是来解决这个痛点的。它只关心左侧操作数是不是 null 或者 undefined。如果不是,那它就直接返回左侧的值,哪怕这个值是 0、false 或者是 ''。

举个例子:

JavaScript如何用空值合并运算符设置默认值
// 传统 || 的问题
const count = 0;
const defaultCount = 10;
const finalCount_or = count || defaultCount; // finalCount_or 是 10,因为 0 是假值

const isActive = false;
const defaultActive = true;
const finalActive_or = isActive || defaultActive; // finalActive_or 是 true,因为 false 是假值

const userName = '';
const defaultUserName = 'Guest';
const finalUserName_or = userName || defaultUserName; // finalUserName_or 是 'Guest',因为 '' 是假值

console.log('使用 ||:', { finalCount_or, finalActive_or, finalUserName_or });
// 输出: 使用 ||: { finalCount_or: 10, finalActive_or: true, finalUserName_or: "Guest" }

// 使用 ?? 的解决方案
const count_nullish = 0;
const finalCount_nullish = count_nullish ?? defaultCount; // finalCount_nullish 是 0

const isActive_nullish = false;
const finalActive_nullish = isActive_nullish ?? defaultActive; // finalActive_nullish 是 false

const userName_nullish = '';
const finalUserName_nullish = userName_nullish ?? defaultUserName; // finalUserName_nullish 是 ''

const address = null;
const defaultAddress = '未知地址';
const finalAddress_nullish = address ?? defaultAddress; // finalAddress_nullish 是 '未知地址'

const phone = undefined;
const defaultPhone = '无';
const finalPhone_nullish = phone ?? defaultPhone; // finalPhone_nullish 是 '无'

console.log('使用 ??:', { finalCount_nullish, finalActive_nullish, finalUserName_nullish, finalAddress_nullish, finalPhone_nullish });
// 输出: 使用 ??: { finalCount_nullish: 0, finalActive_nullish: false, finalUserName_nullish: "", finalAddress_nullish: "未知地址", finalPhone_nullish: "无" }

这下就清楚多了,?? 给了我们更精细的控制,它只在真正“没有值”(null 或 undefined)的时候才提供默认值。

JavaScript中空值合并运算符(??)与逻辑或(||)运算符的核心差异是什么?

说白了,?? 和 || 最核心的区别在于它们判断一个值是否“空”的标准。|| 运算符遵循的是 JavaScript 的“真值/假值”概念。在 JavaScript 里,除了 false、0、'' (空字符串)、null、undefined 和 NaN 之外,所有值都被认为是“真值”。所以,当 || 的左侧操作数是上述任何一个“假值”时,它就会返回右侧的操作数。这在某些场景下,比如简单的布尔判断或者确保一个变量有“非空”值时,确实挺方便的。

但 ?? 运算符则完全不同。它只关注两种特定的“空”状态:null 和 undefined。只有当左侧操作数是 null 或 undefined 时,?? 才会返回右侧的操作数。这意味着,如果左侧操作数是 0、false、'' 甚至是 NaN,?? 都会认为它们是有效值,并直接返回左侧操作数。

这种差异在处理不同类型数据时尤为重要。比如,你从后端API拿到的数据,某个字段可能明确返回 0 表示数量为零,而不是缺失;或者返回 false 表示某个功能是关闭的。如果这时候你还用 || 去设置默认值,那就会把这些有效的 0 或 false 误判成“需要默认值”的情况,导致数据被意外修改。而 ?? 则能准确地识别出,这些 0 或 false 确实是数据本身带有的值,无需替换。对我来说,这种精确性在编写健壮的前端应用时,简直是救命稻草。

什么时候应该优先选择空值合并运算符(??)而非逻辑或(||)?

我个人觉得,当你需要为变量设置默认值,并且 0、false 或空字符串 '' 在你的业务逻辑中被视为有效的、非默认值时,就应该毫不犹豫地选择 ??。

举几个常见的例子:

  1. 处理数值型数据:比如用户输入的年龄、商品库存数量、某个评分。如果用户输入了 0,或者库存确实是 0,这通常是一个有效状态,而不是“缺失”或“未定义”。如果用 ||,0 || 默认值 就会变成 默认值,这显然不是我们想要的。?? 则能保留这个 0。

    const userAge = 0; // 用户明确输入了0岁
    const displayAge = userAge ?? 18; // displayAge 是 0,而不是 18
  2. 处理布尔型标志:在配置对象或用户设置中,false 可能表示某个功能被明确禁用。如果用 ||,false || true 就会变成 true,导致功能意外开启。?? 就能准确地保留 false。

    const enableFeature = false; // 用户明确关闭了某个功能
    const finalFeatureState = enableFeature ?? true; // finalFeatureState 是 false
  3. 处理字符串型数据:当空字符串 '' 在你的应用中代表一种有效状态(比如用户清空了某个文本输入框,表示“无内容”,而不是“未填写”),|| 会把它替换成默认值。?? 则会保留这个空字符串。

    const comment = ''; // 用户提交了空评论
    const displayComment = comment ?? '无评论'; // displayComment 是 ''
  4. 处理来自外部系统的数据:比如从API获取的JSON数据,某个字段可能明确返回 null 表示“无此信息”,或者根本没有这个字段(undefined)。但如果它返回 0 或 false,那通常是有意义的。在这种情况下,?? 能够更安全、更准确地处理这些值。

总的来说,当你对“空”的定义非常严格,只认为 null 和 undefined 是真正的“空”,而其他假值(0, false, '', NaN)都是有效值时,?? 就是你的首选。|| 依然有它的用武之地,比如在纯粹的布尔逻辑判断,或者当你确实希望所有假值都回退到默认值时。但我的经验是,在设置默认值这件事情上,?? 往往能避免很多隐晦的bug。

在实际项目开发中,空值合并运算符(??)还有哪些高级或组合用法?

?? 这玩意儿,除了上面说的基本用法,在实际项目里还有不少挺有意思的组合拳,能让代码写得更健壮、更简洁。

  1. 链式空值合并:你可以把多个 ?? 运算符串起来,实现多级回退。这在处理复杂的配置或者从多个源获取数据时特别有用。比如,我可能先尝试从用户设置里拿一个值,如果用户没设置(null 或 undefined),就去全局配置里找,如果全局配置也没有,再给一个硬编码的默认值。

    const userConfig = { theme: null }; // 用户没有明确设置主题
    const globalConfig = { theme: 'dark' }; // 全局配置有默认主题
    const fallbackTheme = 'light'; // 最终兜底主题
    
    // 尝试从 userConfig.theme 获取,如果是 null/undefined,则尝试 globalConfig.theme,
    // 如果还是 null/undefined,则使用 fallbackTheme
    const currentTheme = userConfig.theme ?? globalConfig.theme ?? fallbackTheme;
    console.log(currentTheme); // 输出: "dark"
    
    const userFont = undefined;
    const globalFont = undefined;
    const fallbackFont = 'sans-serif';
    const finalFont = userFont ?? globalFont ?? fallbackFont;
    console.log(finalFont); // 输出: "sans-serif"

    这种方式比写一堆 if/else 或者三元运算符要清晰得多。

  2. 结合可选链运算符 ?.:这俩简直是天作之合。当你在访问一个可能不存在的对象属性时,?. 可以防止报错,返回 undefined。而 ?? 紧随其后,就能优雅地为这个可能 undefined 的结果提供一个默认值。这在处理从后端API拿到的嵌套数据时,简直是神器。

    const userData = {
        id: 1,
        profile: {
            name: 'Alice',
            address: null // 地址可能为 null
        }
    };
    
    // 假设另一个用户数据,可能没有 profile
    const anotherUserData = {
        id: 2
    };
    
    // 获取用户地址,如果 profile 或 address 不存在/为 null,则默认为 '未填写'
    const aliceAddress = userData.profile?.address ?? '未填写';
    console.log(aliceAddress); // 输出: "未填写"
    
    const bobAddress = anotherUserData.profile?.address ?? '未填写';
    console.log(bobAddress); // 输出: "未填写"
    
    // 如果 profile.name 存在且不为 null/undefined
    const aliceName = userData.profile?.name ?? '匿名';
    console.log(aliceName); // 输出: "Alice"

    这种组合让数据访问和默认值设置变得异常简洁和安全,大大减少了 if (obj && obj.prop) 这样的冗余判断。

  3. 在函数参数默认值之外的补充:虽然ES6有函数参数默认值(function foo(bar = defaultValue)),但有时候参数可能被明确传入 null 或 undefined。如果你希望这种明确传入的 null 或 undefined 也能触发默认行为,?? 可以在函数体内部作为一种补充。

    function processValue(value) {
        // 如果 value 是 null 或 undefined,则使用 'default'
        const finalValue = value ?? 'default';
        console.log(`处理的值: ${finalValue}`);
    }
    
    processValue(0);      // 输出: 处理的值: 0
    processValue(false);  // 输出: 处理的值: false
    processValue('');     // 输出: 处理的值:
    processValue(null);   // 输出: 处理的值: default
    processValue(undefined); // 输出: 处理的值: default
    processValue();       // 输出: 处理的值: default

    这与函数参数默认值略有不同,函数参数默认值只在参数未传入(undefined)时生效,而 ?? 可以处理明确传入的 null。

这些用法让 ?? 不仅仅是一个简单的赋值操作符,它成了构建健壮、可读性高代码的利器,尤其是在处理不确定数据源和复杂配置时,它的价值就体现得淋漓尽致。

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

2275

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

3682

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

1236

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

4259

2025.09.10

es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

305

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

406

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

395

2025.12.24

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

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

549

2023.09.22

Postman身份认证怎么配置
Postman身份认证怎么配置

本专题从实际API接口调试场景出发,讲解Postman身份认证的完整配置流程,包括常见认证协议介绍、授权参数设置、访问令牌填写、OAuth 2.0授权及认证失败排查,帮助用户正确完成接口授权与访问验证。

0

2026.11.06

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Postman安装指南
Postman安装指南

共0课时 | 0人学习

DBeaver生态工具dbvr官方手册
DBeaver生态工具dbvr官方手册

共0课时 | 0人学习

DBeaver事务控制指南
DBeaver事务控制指南

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn