Operador de coalescência nula

O operador de coalescência nula (??) é um operador lógico que retorna o seu operando do lado direito quando o seu operador do lado esquerdo é null ou undefined. Caso contrário, ele retorna o seu operando do lado esquerdo.

Ao contrário do operador lógico OR (||), o operando esquerdo é retornado se houver um valor falsy (falso) que não seja null ou undefined. Em outras palavras, se você usar || para obter algum valor padrão para outra variável foo, você pode enfrentar comportamentos inesperados se você considerar algum valor falseável como utilizável (eg. '' ou 0). Veja abaixo alguns exemplos:

Sintaxe

exprEsq ?? exprDir

Descrição

O operador de coalescência nula retorna os resultados da expressão de seu lado direito se a expressão de seu lado esquerdo for null ou undefined.

Endereçando um valor padrão à variável

Inicialmente, quando se deseja endereçar um valor padrão à variável, um padrão comum é utilizar o operador lógico OR  (||):

let foo;

//  foo nunca é endereçado a nenhum valor, portanto, ainda está indefinido
let someDummyText = foo || 'Hello!';

Entretanto, devido ao || ser um operador lógico booleano, o operando do lado esquerdo é coagido para um valor booleano para sua avaliação, e, qualquer valor falseável (0, '', NaN, null, undefined) não é retornado. Este comportamento pode causar consequencias inesperadas se você considerar 0, '', or NaN como valores válidos.

let count = 0;
let text = "";

let qty = count || 42;
let message = text || "Olá!";
console.log(qty);     // 42 e não 0
console.log(message); // "hi!" e não ""

O operador de coalescência nula evita esta cilada pois retorna o segundo operando apenas quando o primeiro é avaliado entre os valores null ou undefined (mas nehum outro valor falseável):

let myText = ''; // Uma string vazia (que também é um valor falseável)

let notFalsyText = myText || 'Olá mundo';
console.log(notFalsyText); // Olá mundo

let preservingFalsy = myText ?? 'Olá vizinhança';
console.log(preservingFalsy); // '' (Pois myText não é undefined e nem null)

Curto-circuito

Assim como os operadores lógicos OR e AND, a expressão do lado direito não é avaliada se o lado esquerdo não for avaliado entre null e nem undefined.

function A() { console.log('A foi chamado'); return undefined;}
function B() { console.log('B foi chamado'); return false;}
function C() { console.log('C foi chamado'); return "foo";}

console.log( A() ?? C() );
// Imprime "A foi chamado" então "C foi chamado" e por fim "foo"
// Como A() retornou undefined então ambas expressões foram avaliadas

console.log( B() ?? C() );
// Imprime "B foi chamado" então "false"
// Como B() retornou false (e não null ou undefined), a expressão
// do lado direito não foi avaliada.

Sem encadeamento com os operadores AND e OR

Não é possível encadear ambos operadores AND (&&) e OR (||) diretamente com o ??. Um SyntaxError (en-US) será disparado nesse tipo de caso.

null || undefined ?? "foo"; // Dispara um SyntaxError
true || undefined ?? "foo"; // Dispara um SyntaxError

Entretanto, explicitar diretamente a precedência por meio de parênteses resulta no comportamento correto:

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

Relacionamento com o operador de encadeamento opcional (?.)

O operador de coalescêcia nula trata undefined e null como valores específicos e então executa o operador de encadeamento opcional (?.) o qual é útil para acessar uma propriedade de um objeto, o qual pode ser null ou undefined.

let foo = { someFooProp: "oi" };

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

Exemplo

Neste exemplo, nós iremos prover valores padrão, mas manter valores que não sejam (advinha???) null ou undefined.

const nullValue = null;
const emptyText = ""; // falseável (falsy)
const someNumber = 42;

const valA = nullValue ?? "padrão para A";
const valB = emptyText ?? "padrão para B";
const valC = someNumber ?? 0;

console.log(valA); // "padrão para A"
console.log(valB); // "" (pois a string vazia não é null ou undefined)
console.log(valC); // 42

Especificações

Especificação Status comentário
Proposal for the "nullish coalescing" operator Stage 4

Compatibilidade de navegadores

BCD tables only load in the browser

Veja também