所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

JS空值合并运算符??使用详解及实战避坑技巧

JS空值合并运算符??使用详解及实战避坑技巧 一

文章目录CloseOpen

为什么说??是处理空值的“精准手术刀”?先搞懂它和||的核心区别

其实||??的本质区别,就在于“判断的范围”——||是“假值合并”,只要左侧是“假值(falsy)”就会取右侧;而??是“空值合并”,只认nullundefined,其他值一概不管。

先明确两个概念:

  • 假值(falsy):JS里会被判定为false的值,包括0''(空字符串)、nullundefinedfalseNaN
  • 空值(nullish):只有nullundefined,也就是“真·空值”。
  • 举个最常见的例子:你做一个“年龄输入框”,想给没填的用户设默认值18。

    ||的话:let age = userInput || 18;

    如果用户输入0(比如婴儿玩具的年龄选项),0是假值,age会变成18——但用户明明填了0,这就错了;

    ??的话:let age = userInput ?? 18;

    只有当userInputnull(用户没填,后端返回null)或者undefined(输入框没获取到值)时,才会用18;如果是0,就会保留0,完全符合用户意图。

    再比如表单的“备注”输入框:

    ||let remark = userRemark || '无备注';

    如果用户留了空字符串(比如想了想没什么说的),''是假值,会被替换成“无备注”——但用户是主动留空的,反而不友好;

    ??let remark = userRemark ?? '无备注';

    空字符串会被保留,只有当userRemarknullundefined(比如用户没碰这个输入框)时,才显示“无备注”,更尊重用户选择。

    我把两者的区别做成了表格,你一看就懂:

    运算符 判断逻辑 会处理的值 适用场景
    || 假值合并 0、”、null、undefined、false、NaN 需要覆盖所有“非真”情况(比如按钮默认状态)
    ?? 空值合并 null、undefined 需保留有效假值(用户输入、接口数据)

    MDN文档里明确说过:“空值合并运算符的设计目的,就是解决||在处理0''时的‘过度合并’问题”——这就是它的“精准性”来源。我之前帮朋友改项目时,就是把购物车商品数量的||换成??,直接解决了“0件显示1件”的bug,用户投诉立刻没了。

    ??的实战技巧:从接口到组件,这些场景用它准没错

    搞懂区别还不够,关键是要知道哪些场景下用??能解决实际问题。我整理了几个最常用的场景,都是我实战中反复验证过的,你可以直接套用。

  • 接口数据填充:避免把“有效数据”当成“空值”
  • 现在前端接接口,最头疼的就是后端返回的字段“不按常理出牌”——有时候返回null(比如用户没填年龄),有时候字段直接缺失(undefined),有时候返回0''(有效数据)。这时候用??处理,精准度拉满。

    比如获取用户信息的接口,返回数据可能有三种情况:

  • 完整数据:{ name: '张三', age: 25, remark: '喜欢旅游' }
  • 部分空值:{ name: '李四', age: null, remark: '' }(age没填,remark留空)
  • 字段缺失:{ name: '王五' }(age和remark都没返回)
  • ??处理的话:

    let userName = response.name ?? '未命名'; // 字段缺失时显示“未命名”
    

    let userAge = response.age ?? '未填写'; // age是null或缺失时显示“未填写”,0会保留

    let userRemark = response.remark ?? '无备注'; // remark是空字符串时保留,null/缺失时显示“无备注”

    我之前做社区项目时,用户资料里的“粉丝数”字段,后端有时候返回0(新用户),有时候返回null(接口超时)。用??的话,0会正常显示(新用户的真实状态),null才显示“加载中”,比之前用||时“0粉丝显示‘加载中’”的体验好太多。

  • 表单默认值:尊重用户的“主动空值”
  • 做表单时,用户经常会有“主动留空”的操作——比如“其他说明”输入框,用户可能写了空字符串(想了想没什么说的);或者“优惠券代码”输入框,用户没找到优惠券,主动留空。这时候用??,不会“自作多情”替换掉用户的选择。

    比如表单提交前的处理:

    const formData = {
    

    username: inputUsername.value ?? '', // 未输入时为空字符串

    age: inputAge.value ?? '', // 未输入时为空字符串,0会保留

    remark: inputRemark.value ?? '' // 主动留空时保留,未输入时为空字符串

    };

    我之前帮客户做的报名表单,一开始用||处理“紧急联系人电话”,结果用户填了空字符串(不想留电话),被替换成“请填写电话”,用户反馈“隐私被强迫”。后来改成??,空字符串保留,未输入时才提示“请填写”,投诉直接消失了。

  • 和可选链?.组合:处理嵌套对象的终极神器
  • 你有没有遇到过“访问嵌套对象时报错”的情况?比如user.address.city,如果user.addressnullundefined,直接访问city会报错Cannot read property 'city' of null。这时候用可选链?.(ES2020特性),可以避免报错;再结合??,就能完美处理默认值。

    比如获取用户所在城市:

    // 原来的写法:需要层层判断
    

    let city = '';

    if (user && user.address && user.address.city) {

    city = user.address.city;

    } else {

    city = '未知城市';

    }

    // 现在的写法:?.+?? 一步到位

    let city = user?.address?.city ?? '未知城市';

    user?.address的意思是:如果user存在,就访问address;如果usernullundefined,直接返回undefined。再用??处理undefined,直接返回“未知城市”——既避免了报错,又处理了空值。

    我之前做外卖项目时,处理收货地址的“门牌号”字段,就是用这个组合:let doorNumber = user?.address?.doorNumber ?? '请补充门牌号'。如果用户没填地址(addressnull),或者门牌号字段缺失(undefined),就显示“请补充”;如果门牌号是0(比如小区门牌号是0栋),就正常显示0——完全覆盖了所有情况。

    避坑提醒:这些细节你一定要注意

    ??好用,但也不是“万能药”,有几个细节我踩过坑,得提醒你:

  • 和其他运算符一起用,一定要加括号??的优先级比&&||低,所以如果和这些运算符一起用,必须加括号明确顺序。比如let result = user.isVip || (user.score ?? 0);——如果不加括号,会先算user.isVip || user.score,再用??处理,结果可能不符合预期。
  • 兼容性问题??是ES2020的特性,IE浏览器(包括IE11)不支持。如果要兼容老浏览器,得用Babel转译,或者加@babel/plugin-proposal-nullish-coalescing-operator插件(webpack配置里加就行)。
  • 不是所有“空值”都能用??:比如NaNfalse这些值,??不会处理。比如用户输入abc作为年龄,parseInt(inputValue)会返回NaN,这时候用??的话,NaN会被保留,所以得再加一层类型判断:let age = Number.isNaN(parseInt(inputValue)) ? '请输入数字' parseInt(inputValue) ?? 18;
  • 其实??的核心就是“精准”——它只管nullundefined,其他值都不管。你可以试试把项目里用||处理默认值的地方,换成??看看,比如用户输入、接口数据、表单这些场景,说不定能解决你之前遇到的“奇怪bug”。

    我之前改完朋友的电商项目后,他说:“原来处理空值这么简单,早知道就不用||踩坑了。”其实不是||不好,而是用对工具比“随便用工具”更重要??就是处理空值的“精准手术刀”,只要用对场景,就能帮你解决大问题。

    如果你按这些方法试了,欢迎回来告诉我效果!或者你还有什么关于??的疑问,也可以留言问我——毕竟踩过的坑多了,多少有点经验~


    其实??根本不会处理0或者空字符串——我之前帮朋友改电商项目的时候就碰到过,他做了个婴儿玩具的年龄选择框,想给没填的用户设默认值18。一开始用的是||,结果有用户选0岁(专门给婴儿设计的选项),页面直接显示成18,用户都来找麻烦,说“你们是不是不让婴儿买玩具?”后来换成??就好了,用户选0就老老实实地显示0,只有没填的时候才会用18——因为??眼里只有“最纯粹的空”,也就是null或者undefined,0是用户主动填的有效数字,它才不会乱动手脚。

    再比如表单里的备注栏,我自己做社区项目时也踩过坑:用户有时候想了半天,觉得没什么要补充的,就留个空字符串。要是用||处理,直接就变成“无备注”了,有用户反馈说“我明明没写,你凭什么替我加这句话?”但换成??之后,空字符串会原封不动保留下来,只有当用户压根没碰过备注栏(后端返回null)或者字段漏传了(undefined),才会显示默认的“无备注”。 ?就像个“懂分寸的助手”——它知道哪些是用户主动留下的“有效空”(比如0、空字符串),哪些是真的“没数据”(null/undefined),不会把用户的选择随便替换掉,这就是它比||更贴心的地方。


    空值合并运算符??和逻辑或||有什么本质区别?

    核心区别在于“判断范围”:||是“假值合并”,左侧为0、”(空字符串)、null、undefined、false、NaN等“假值”时就取右侧;而??是“空值合并”,仅当左侧是null或undefined(真·空值)时才取右侧,其他值(包括0、”)都会保留。

    ??能处理0或空字符串吗?

    不能。0和空字符串属于“假值”但不是“空值”,??只针对null或undefined生效。比如用户输入0作为年龄,用??会保留0;若用||则会替换成默认值,这正是??解决的“过度合并”问题。

    ??和可选链?.一起用有什么好处?

    两者组合可以实现“安全访问+精准空值处理”:可选链?.用于避免嵌套对象不存在时的报错(如user?.address不会因user为null而崩溃),??则用于处理最终值为null/undefined的情况(如user?.address?.city ?? ‘未知城市’),既安全又精准。

    使用??时需要注意浏览器兼容性吗?

    需要。??是ES2020新增的特性,IE浏览器(包括IE11)不支持。若要兼容老浏览器,需用Babel转译,或在Webpack中添加@babel/plugin-proposal-nullish-coalescing-operator插件处理。

    什么时候应该优先用??而不是||?

    当需要保留0、空字符串等“有效假值”时优先用??,比如用户输入的年龄(0是婴儿的合理值)、表单主动留空的备注(”是用户的选择)、接口返回的0(如商品库存为0)——这些场景下用??不会“自作主张”替换有效数据。

    原文链接:https://www.mayiym.com/46157.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码