JavaScript 中的逻辑赋值运算符教程:小语法、大价值

52 阅读4分钟

原文链接:Logical assignment operators in JavaScript: small syntax, big wins,2025.07.28,by Matt Smith。

在日常的 JavaScript 开发中,我们经常需要先检查变量再为其赋值。不过在 JavaScript 中这种检查会很繁琐,尤其是在处理组件属性(component props)、全局配置(global configs)或状态对象(state objects)时。这时,逻辑赋值运算符(logical assignment operators) 就派上用场了——它是ES2021中新增的一个简洁特性,能简化常见的条件赋值操作,同时不改变底层逻辑。

什么是逻辑赋值运算符?

逻辑赋值运算符将逻辑运算符(||&&??赋值运算符(= 结合,提供一种简写形式。这些运算符和常规的逻辑表达式一样支持短路求值(short-circuit),也就是说只有当左侧不符合测试条件(即为假值、真值或空值)时,才会对右侧进行求值。

⚠️ 注意:可选链(Optional chaining,?.)不允许用于逻辑赋值的左侧,否则会抛出语法错误:

// ❌ 语法错误:
user?.settings ||= {};

可选链返回的是属性访问的结果,而非属性本身的引用。由于赋值目标必须是引用(即变量或对象属性),所以上述写法是无效的。

逻辑或赋值(||=

当左侧为假值(falsy) 时赋值:

user.theme ||= 'light';

等价于:

if (!user.theme) {
  user.theme = 'light';
}

这在没有初始化值的场景设置默认值时很有用。但是,它会覆盖0''false这类可能是有意设置的值。

逻辑与赋值(&&=

当左侧为**真值(truthy)**时赋值:

user.isLoggedIn &&= checkPermissions(user);

等价于:

if (user.isLoggedIn) {
  user.isLoggedIn = checkPermissions(user);
}

这有助于根据已有的真值条件更新值。

⚠️ 注意:使用&&=时,只有当左侧为真值时才会对右侧求值,并将右侧的实际结果赋值给左侧,即便该结果是假值也不例外。

let isEnabled = true;
isEnabled &&= false;
console.log(isEnabled); // false

原始值(true)起到了“ gate”的作用,但最终是右侧表达式的结果成为新值。&&=不会保留旧值,而是直接替换它。

空值合并赋值(??=

当左侧为空值nullundefined)时赋值:

settings.timeout ??= 3000;

等价于:

if (settings.timeout === null || settings.timeout === undefined) {
  settings.timeout = 3000;
}

当你只想在值确实缺失时赋值默认值,就可以使用这个运算符。与||=不同,它会保留0false''这类有效的值。

为什么逻辑赋值在代码中很重要?

这些运算符不只是语法糖。它们能更安全、更易读地解决实际问题,尤其是在处理可变状态(mutable state)时:

这些运算符会直接修改原始对象或变量。这在有状态逻辑中可能很有用,但在不可变工作流(如Redux)中可能会导致错误。如果需要保留状态历史,需要先克隆对象。

为组件属性设置默认值

props.showHelpText ??= true;

避免覆盖全局状态或配置

config.apiBase ||= '/api/v1';

防止意外的null/undefined赋值

formData.username &&= formData.username.trim();

但要注意

  • ||=会在左侧为假值时赋值,这会覆盖包括0''false在内的场景,而这些值可能是你想要保留的。
let count = 0;
count ||= 10; // 会将count覆盖为10,要小心!
  • 当你想专门针对nullundefined进行防护,并保留有效的假值时,使用??=
  • 右侧表达式仅在必要时才会求值,这样能保证性能并避免副作用。
config.apiKey ||= fetchApiKey(); // 只有当apiKey为假值时,才会执行fetchApiKey()

带有副作用的示例

let calls = 0;
let obj = { val: 0 };

obj.val ||= ++calls;
console.log(obj.val); // 1,因为0是假值

obj.val ||= ++calls;
console.log(obj.val); // 仍然是1,第二次递增不会执行

由于obj.val最初是0(假值),所以会对++calls求值并赋值。在第二次执行时,obj.val现在是1(真值),因此++calls会被跳过。calls的值仍然是1

浏览器支持情况

逻辑赋值运算符在所有现代环境中都得到支持:

  • ✅ Chrome 85+、Firefox 79+、Safari 14+、Edge 85+
  • ✅ Node.js 15+
  • ❌ 不支持Internet Explorer

如果要兼容旧环境,可以使用@babel/preset-env这类转译工具,并配置ES2021设置。

现在就可以使用了

逻辑赋值运算符是JavaScript中一个虽小但强大的新增特性。它们能明确你的语义意图,减少样板代码,并简化常见的条件逻辑。

在前端工作流中,它们尤其有用,例如:

  • 属性和状态管理
  • API默认值设置
  • 表单整理

如果你已经熟练使用||&&??,那么掌握||=&&=??=对大家来说只是水到渠成的事。