逻辑赋值运算符 ||=、&&=、??= 有什么区别?
简化版
逻辑赋值运算符把逻辑判断和赋值合在一起:||= 在左侧为假值时赋值,&&= 在左侧为真值时赋值,??= 在左侧为 null 或 undefined 时赋值。
最常用的是 ??= 做默认值,因为它不会把 0、空字符串、false 当成缺失值。
详细版
let a = 0;
a ||= 10;
console.log(a); // 10
let b = 0;
b ??= 10;
console.log(b); // 0
&&= 常用于存在时更新:
let user = { name: "Ada" };
user &&= { ...user, active: true };
它们都会短路,只有满足条件时才会执行右侧表达式。
config.cache ??= createDefaultCache();
如果 config.cache 已存在,右侧函数不会执行。
完整版教学
一、三个运算符分别对应三种判断
| 运算符 | 赋值条件 | 常见用途 |
|---|---|---|
| ` | =` | |
&&= | 左侧是真值 | 存在时更新 |
??= | 左侧是 null 或 undefined | 缺失值默认值 |
真正常用的判断是:你要处理“假值”,还是只处理“空值”。
二、||= 的假值规则
JavaScript 假值包括 false、0、""、null、undefined、NaN。
let pageSize = 0;
pageSize ||= 20;
console.log(pageSize); // 20
如果 0 是合法值,这个写法就是 bug。
三、??= 更适合默认值
let pageSize = 0;
pageSize ??= 20;
console.log(pageSize); // 0
??= 只把 null 和 undefined 视为缺失,不误伤合法假值。
数字例子:分页大小允许为 0 表示“不分页”时,||= 会把它改成 20,??= 不会。
四、&&= 适合存在时替换
let token = "abc";
token &&= mask(token);
如果左侧是假值,右侧不会执行。
let token = "";
token &&= mask(token);
console.log(token); // ""
它常用于“有值才进一步处理”的场景,但业务代码中不要为了省几行让意图变晦涩。
五、短路意味着右侧可能不执行
let cache = {};
cache.store ??= createStore();
只有 cache.store 是 null 或 undefined 时,createStore() 才会调用。
这对性能和副作用都重要:右侧如果有日志、请求或对象创建,不一定发生。
六、和属性赋值的关系
逻辑赋值也可以用于对象属性。
options.timeout ??= 3000;
options.debug ||= false;
如果对象本身可能为空,不能直接写:
options?.timeout ??= 3000; // 语法不成立
需要先确保对象存在。
七、常见误区与追问
- 误区:
||=和??=都是设置默认值,效果一样。||=会覆盖所有假值,??=只覆盖空值。 - 误区:逻辑赋值一定会执行右侧表达式。 它们都会短路。
- 误区:
&&=最适合所有条件更新。 条件复杂时显式 if 更清晰。 - 误区:可选链左侧可以直接赋值。 可选链不能作为赋值目标。
- 追问:为什么配置默认值更推荐
??=? 它保留0、空字符串、false这些合法配置值。 - 追问:右侧函数什么时候执行? 只有满足对应赋值条件时才执行。
八、加强记忆
记三个条件:
x ||= y -> if (!x) x = y
x &&= y -> if (x) x = y
x ??= y -> if (x == null) x = y
答题时重点比较 0、""、false 这些合法假值,说明为什么很多默认值场景应该用 ??=。