Nullish coalescing operator

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

逻辑或(||)操作符不同,逻辑或会在左操作数为 假值  时返回右侧操作数。也就是说,如果你使用 || 来为某些变量设置默认的值时,你可能会遇到意料之外的行为。比如为假值(例如,'' 或 0)时。见下面的例子。

语法

leftExpr ?? rightExpr

描述

空值合并运算符会在左侧的表达式为 undefined 时返回右侧的表达式。

为变量赋默认值

在早期,如果想为一个变量赋默认值,通常的做法是使用逻辑或操作符(||):

let foo;
...
//  foo is never assigned any value so it is still undefined
let someDummyText = foo || 'Hello!';

然而由于 || 是一个布尔逻辑运算符,左侧的操作数会被强制转换成布尔值用于求值。任何假值(0, '', NaN, null, undefined)都不会被返回。这导致如果你使用0''NaN作为有效值,就会出现不可预料的后果。

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

空值合并操作符可以避免这种陷阱,其只在第一个操作数为null 或 undefined 时(而不是其它假值)返回第二个操作数:

let myText = ''; // An empty string (which is also a falsy value)

let notFalsyText = myText || 'Hello world';
console.log(notFalsyText); // Hello world

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

短路

与 OR 和 AND 逻辑操作符相似,当左操作符为 null 或 undefined 时,不会对右操作数进行求值。

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

不能与 AND 或 OR 操作符共用

直接与 AND(&&)和 OR(||)操作符组合使用 ?? 是不可取的。这种情况下会抛出 SyntaxError

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

但当使用括号来显式表明优先级时是正确的:

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

与可选链式操作符(?.)的关系

空值合并操作符针对 undefined 与 null 这两个值,可选链式操作符(?. 也是如此。在这访问属性可能为 undefined 与 null 的对象时非常有用。

let foo = { someFooProp: "hi" };

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

样例

在这个例子中,我们会提供默认值,但对原有值不为 undefined 与 null 的进行保留。

function getMiscObj(){
  return {
    aNullProperty: null,
    emptyText: "", // this is not falsy
    someNumber: 42
  };
};

const miscObj = getMiscObj();

const newObj = {};
newObj.propA = miscObj.aNullProperty ?? "default for A";
newObj.propB = miscObj.emptyText ?? "default for B";
newObj.propC = miscObj.someNumber ?? 0;

console.log(newObj.propA); // "default for A"
console.log(newObj.propB); // "" (as the empty string is not null or undefined)
console.log(newObj.propC); // 42

规范

Specification Status Comment
Proposal for the "nullish coalescing" operator Stage 3

浏览器兼容性

Update compatibility data on GitHub
Desktop Mobile Server
Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Safari on iOS Samsung Internet Node.js
Nullish coalescing operator (??)
Experimental
Chrome No support No Edge No support No Firefox No support No IE No support No Opera No support No Safari No support No WebView Android No support No Chrome Android No support No Firefox Android No support No Opera Android No support No Safari iOS No support No Samsung Internet Android No support No nodejs No support No

Legend

No support  
No support
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.

Note: The corresponding PR has been merged and the data should soon be available on the page.

Implementation Progress

The following table provides a daily implementation status for this feature, because this feature has not yet reached cross-browser stability. The data is generated by running the relevant feature tests in Test262, the standard test suite of JavaScript, in the nightly build, or latest release of each browser's JavaScript engine.

See also