|| ?. ?? ??= 4种操作符

JavaScript 中 ||、?.、?? 的含义与用法

一、符号概览

  • || 逻辑或 :返回第一个"真值"(truthy);若都是"假值"(falsy),返回最后一个值。常用于提供默认值与布尔判断。falsy 值包括:false、0、""、null、undefined、NaN。
  • ?. 可选链 :安全访问嵌套属性或调用方法;当链中某项为 null/undefined 时,表达式短路返回 undefined 而不报错。
  • ?? 空值合并 :仅当左侧为 null/undefined 时返回右侧默认值;对 0、""、false 等"假值"会原样保留。
  • 相关扩展:??= 空值合并赋值(仅在左侧为 null/undefined 时赋值)。

二、用法与示例

  • || 逻辑或

    • 规则:返回第一个真值;具有短路特性(左侧为真不再求值右侧)。

    • 示例:

      js 复制代码
      const a = 0 || 10;        // 10(0 是 falsy)
      const b = "" || "Hi";     // "Hi"(空字符串是 falsy)
      const c = null || "def";   // "def"
    • 场景:需要把任何 falsy 都替换成默认值的快捷写法。

  • ?. 可选链

    • 规则:访问 obj?.prop 、obj?.expr 、arr?.index 、func?.() 时,若左侧为 null/undefined 则短路返回 undefined。

    • 示例:

      js 复制代码
      const user = { profile: { name: "A" } };
      console.log(user?.profile?.age);       // undefined
      console.log(user.settings?.theme);    // undefined
      console.log(user.profile.getName?.()); // undefined(方法不存在不报错)
    • 场景:处理 API 深层结构、可能缺失的属性/方法,避免 Cannot read property... 错误。

  • ?? 空值合并

    • 规则:仅当左侧为 null/undefined 时返回右侧;其他值(含 0、""、false)保留。

    • 示例:

      js 复制代码
      const a = 0 ?? 10;        // 0(保留 0)
      const b = "" ?? "Hello";   // ""(保留空字符串)
      const c = null ?? "def";   // "def"
      const d = false ?? true;   // false(保留 false)
    • 场景:需要区分"未设置(null/undefined)"与"显式假值(0、""、false)"的默认值逻辑。

三、如何选择

  • 需要安全访问可能为 null/undefined 的深层属性或方法:用 ?.。
  • 只想在值为 null/undefined 时给默认值,同时保留 0、""、false :用 ??。
  • 希望把所有 falsy (如 0、""、false )都替换成默认值:用 ||。
  • 需要"仅当缺失才赋值"的简写:用 ??=。

四、组合与注意

  • 常见组合:先安全取值,再给默认值,避免报错与误覆盖。

    js 复制代码
    const city = user?.address?.city ?? "未知城市";
  • 与运算优先级:表达式中混用 ?? 与 &&/|| 必须用括号明确顺序,否则语法错误。

    js 复制代码
    // 错误:let x = a && b ?? c;
    let x = (a && b) ?? c; // 正确
  • 不能对可选链左侧直接赋值:

    js 复制代码
    obj?.prop = 1; // SyntaxError
  • 浏览器/环境支持提示:?. 与 ?? 为 ES2020 特性;如需兼容旧环境,请使用 Babel 等转译工具。

相关推荐
lpfasd1236 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse4569 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai9 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记10 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化
赵大仁10 小时前
官网性能优化实战:LCP 3.2s → 2.1s、CLS 0.107 → 0,以及被我推翻的 6 个判断
前端·性能优化·cls·lcp·core web vitals
xiancai_xianyu10 小时前
Text2SQL落地生产库前,SQL要过哪三道闸
前端·数据库·sql·sql注入·text2sql·ai agent开发·企业级ai框架
小羊没烦恼!11 小时前
T-SQL查询进阶--理解SQL SERVER中的分区表
服务器·开发语言·前端·javascript·html
史瓦辛格11 小时前
给 DeepSeek Harness 写费用插件:把「这次会话花了多少钱」算准
前端·deepseek
星光不问赶路人11 小时前
Vue 3 + TypeScript 中 enum 的使用实践
前端·vue.js
鸥梨菌Honevid11 小时前
UVM 中 REQ 和 RSP 类型详解:从通信模型到 item_done 与 put_response
java·前端·servlet