逻辑赋值运算符是针对配置初始化的精准工具:??=仅在null/undefined时赋默认值,保留0/false/"";&&=仅当左侧为真值时才执行右侧更新;||=适用于不敏感假值的兜底场景。

逻辑赋值运算符不是语法糖的堆砌,而是针对配置初始化这类高频场景的精准工具。它们把“判断是否存在→再决定是否写入”的两步动作,压缩成一次安全、无副作用的原子操作,代码量减少一半,可读性反而提升。
??=:专治“空值兜底”,保留合法假值
旧写法常误用 ||= 给配置设默认值,结果把 0、false、"" 这类有意设置的值也覆盖了。
- ❌ 错误兜底:
config.timeout ||= 3000;→ 若config.timeout = 0(表示禁用超时),会被强行改成3000 - ✅ 正确兜底:
config.timeout ??= 3000;→ 只有config.timeout是null或undefined才赋值,0、false、""全部原样保留 - ? 实战建议:所有配置项的默认值填充,优先用
??=;尤其适用于 API 超时、重试次数、开关状态等可能显式设为0或false的字段
&&=:只在“当前有效”时才更新,避免无效覆盖
&&= 不是设默认值,而是做条件更新——左侧必须为真值,右侧表达式才会执行并赋值。
- ❌ 冗余更新:
if (user.token) { user.permissions = fetchPerms(user.token); } - ✅ 一行替代:
user.permissions &&= fetchPerms(user.token);→ 若user.token不存在或为空,fetchPerms根本不调用,无副作用 - ? 实战建议:用于链式依赖配置,比如“仅当环境变量存在时才解析为 JSON”:
process.env.DB_CONFIG &&= JSON.parse(process.env.DB_CONFIG);
||=:适合布尔型/字符串型兜底,但需警惕假值陷阱
||= 判断的是 falsy 值,语义是“只要没值就补一个”,适合对真假不敏感的场景。
- ✅ 合理使用:
user.role ||= 'guest';—— 角色一般不会设为0或false,用||=简洁安全 - ⚠️ 高危误用:
user.age ||= 18;—— 若user.age = 0(真实年龄为 0 的婴儿),会被错误覆盖 - ? 实战建议:仅用于明确不会出现
0、false、""的字段,如用户名、主题名、日志级别('info'/'warn')等
重构时不用全盘替换,先从最易出错的配置兜底开始:把所有 if (!x) x = y 和 x = x || y 替换为 x ??= y,再逐个审视是否该用 &&= 或保留 ||=。改完后逻辑更贴近业务意图,也不再担心 getter 多次触发或属性重复读取。










