空值合并运算符 (??)

**空值合并运算符 (??)** 是一种逻辑运算符,当其左侧操作数为 nullundefined 时返回其右侧操作数,否则返回其左侧操作数。

试一试

语法

js
leftExpr ?? rightExpr

描述

空值合并运算符可以看作是 逻辑或 (||) 运算符 的特例。后者当左侧操作数为任何 假值 时返回右侧操作数,而不仅仅是 nullundefined。换句话说,如果您使用 || 为另一个变量 foo 提供一些默认值,如果您认为某些假值可用(例如 ''0),可能会遇到意外行为。有关更多示例,请参阅 下方

空值合并运算符具有第五低的 运算符优先级,直接低于 ||,直接高于 条件(三元)运算符

无法将 AND (&&) 和 OR 运算符 (||) 直接与 ?? 组合。在这种情况下,将抛出 语法错误

js
null || undefined ?? "foo"; // raises a SyntaxError
true && undefined ?? "foo"; // raises a SyntaxError

相反,请提供括号以明确指示优先级。

js
(null || undefined) ?? "foo"; // returns "foo"

示例

使用空值合并运算符

在本例中,我们将提供默认值,但保留除 nullundefined 之外的值。

js
const nullValue = null;
const emptyText = ""; // falsy
const someNumber = 42;

const valA = nullValue ?? "default for A";
const valB = emptyText ?? "default for B";
const valC = someNumber ?? 0;

console.log(valA); // "default for A"
console.log(valB); // "" (as the empty string is not null or undefined)
console.log(valC); // 42

为变量分配默认值

之前,当人们想要为变量分配默认值时,常见的模式是使用逻辑或运算符 (||)

js
let foo;

// foo is never assigned any value so it is still undefined
const someDummyText = foo || "Hello!";

但是,由于 || 是布尔逻辑运算符,因此左侧操作数将被强制转换为布尔值以进行评估,并且任何假值(包括 0''NaNfalse 等)都不会被返回。如果您认为 0''NaN 是有效值,这种行为可能会导致意外后果。

js
const count = 0;
const text = "";

const qty = count || 42;
const message = text || "hi!";
console.log(qty); // 42 and not 0
console.log(message); // "hi!" and not ""

空值合并运算符避免了这种陷阱,因为它仅在第一个操作数评估为 nullundefined(但不是其他假值)时才返回第二个操作数。

js
const myText = ""; // An empty string (which is also a falsy value)

const notFalsyText = myText || "Hello world";
console.log(notFalsyText); // Hello world

const preservingFalsy = myText ?? "Hi neighborhood";
console.log(preservingFalsy); // '' (as myText is neither undefined nor null)

短路

与 'OR' 和 'AND' 逻辑运算符一样,如果左侧表达式被证明既不是 null 也不是 undefined,则不会评估右侧表达式。

js
function a() {
  console.log("a was called");
  return undefined;
}
function b() {
  console.log("b was called");
  return false;
}
function c() {
  console.log("c was called");
  return "foo";
}

console.log(a() ?? c());
// Logs "a was called" then "c was called" and then "foo"
// as a() returned undefined so both expressions are evaluated

console.log(b() ?? c());
// Logs "b was called" then "false"
// as b() returned false (and not null or undefined), the right
// hand side expression was not evaluated

与可选链运算符 (?. ) 的关系

空值合并运算符将 undefinednull 视为特定值。 可选链运算符 (?.) 也是如此,它对于访问可能为 nullundefined 的对象的属性很有用。将它们组合起来,您可以安全地访问可能为空值的属性的对象的属性,并在它是空值时提供默认值。

js
const foo = { someFooProp: "hi" };

console.log(foo.someFooProp?.toUpperCase() ?? "not available"); // "HI"
console.log(foo.someBarProp?.toUpperCase() ?? "not available"); // "not available"

规范

规范
ECMAScript 语言规范
# prod-CoalesceExpression

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅