Um valor padrão mais esperto
O JavaScript sempre teve um atalho para definir valores padrão: value || fallback. Funciona na maioria dos casos, só que traz um probleminha embutido — ele considera qualquer valor falsy como ausente. Ou seja, 0, '' e false acionam o fallback, mesmo quando são exatamente a resposta que você queria.
O operador de nullish coalescing ?? resolve isso. Ele só cai no fallback quando o valor é null ou undefined:
0 e '' sobrevivem. null e undefined não. É isso que o operador faz, em resumo.
Por que o || não resolve
Esse é o bug clássico que o ?? veio corrigir:
O usuário pediu volume 0 (silêncio) e um nickname vazio. Os dois foram sobrescritos sem aviso, porque o || não consegue diferenciar "ausente" de "falsy".
Troque pelo ??:
Agora 0 e '' passam sem serem alterados, e só os campos realmente ausentes recebem o valor padrão. Na prática, é quase sempre isso que você quer.
O modelo mental
O ?? faz uma única pergunta: o lado esquerdo é null ou undefined? Nada além disso importa.
| Valor à esquerda | left || right retorna | left ?? right retorna |
|---|---|---|
null | direita | direita |
undefined | direita | direita |
0 | direita | esquerda (0) |
'' | direita | esquerda ('') |
false | direita | esquerda (false) |
NaN | direita | esquerda (NaN) |
| qualquer objeto | esquerda | esquerda |
Use ?? quando seus dados tiverem valores falsy que fazem sentido. Use || quando você realmente quiser descartar tudo que for falsy (strings vazias, contagens zeradas e afins) — esse caso existe, mas é bem menos comum do que muita gente imagina.
Avaliação em curto-circuito
Assim como || e &&, o ?? também faz curto-circuito. Se o lado esquerdo não for nullish, o lado direito nem chega a ser executado:
expensiveDefault() roda uma vez só — no caso do b. Isso é ótimo quando o seu fallback é uma chamada de função, uma requisição de rede ou qualquer coisa que você prefere evitar quando não for necessário.
Combinando com optional chaining
O ?? e o ?. chegaram juntos no ES2020, e foram pensados para trabalhar em dupla. O optional chaining percorre um caminho que pode não existir e devolve undefined caso algum trecho esteja faltando; já o nullish coalescing entra em cena para fornecer um valor padrão coerente:
Sem essa dupla, o mesmo código vira uma sequência feia de && ou um try/catch. Com elas, acesso seguro e valores padrão cabem em uma única linha.
Atribuição com nullish: ??=
a ??= b atribui b a a apenas quando a é null ou undefined. Esse é o operador de atribuição lógica nullish, e ele tem short-circuit — se a já tem um valor, o lado direito nem chega a ser avaliado.
Repare que verbose: false e retries: 0 foram preservados — o ??= só preenche o que realmente está faltando. Compare com o ||=, que sobrescreveria os dois.
Precedência e a regra dos parênteses
O ?? se recusa de propósito a ser misturado com || ou && sem parênteses. Isso gera um SyntaxError:
const x = a || b ?? c; // SyntaxError
Os criadores da linguagem acharam que a precedência aqui era ambígua o suficiente para exigir que você deixe explícito. Basta colocar parênteses que tudo funciona:
Agrupamentos diferentes, resultados diferentes. Os parênteses não estão ali só de enfeite — eles deixam claro para quem vai ler o código depois (e para o parser) qual era a sua intenção.
Não é a mesma coisa que parâmetro padrão
Os parâmetros padrão na assinatura de uma função seguem outra regra: eles só entram em ação quando o argumento é undefined, e não quando é null. Essa é uma diferença sutil em relação ao ??, que trata os dois casos da mesma forma.
Se quiser que null também dispare o valor padrão, use ?? dentro do corpo:
Distinção pequena, mas fácil de escorregar quando uma API te devolve null significando "sem valor definido".
Quando usar o ??
Use o ?? como seu operador padrão, a não ser que tenha um motivo específico para não usar. Ele é o que reflete melhor como os dados costumam se comportar na prática — 0, '' e false geralmente são valores legítimos que você quer preservar, e só dados realmente ausentes merecem um fallback. Deixe o || para os casos em que você de fato quer substituir qualquer valor falsy.
A seguir: classes
Com isso, fechamos objetos e arrays — agora você tem as ferramentas para montar e navegar por estruturas de dados com segurança. O próximo capítulo muda o foco para organizar comportamento: classes, herança e o sistema de protótipos que sustenta tudo isso.
Perguntas frequentes
O que é o operador nullish coalescing no JavaScript?
O ?? retorna o operando da direita apenas quando o operando da esquerda é null ou undefined. Caso contrário, ele devolve o valor da esquerda sem alterar nada. valor ?? fallback é a forma recomendada de definir um padrão sem cair em armadilhas com valores falsy válidos, como 0 ou ''.
Qual a diferença entre ?? e || no JavaScript?
O || usa o fallback para qualquer valor falsy — 0, '', false, NaN, null, undefined. Já o ?? só entra em ação com null e undefined. Se 0 ou uma string vazia forem valores legítimos nos seus dados, vá de ??. Agora, se a ideia é realmente rejeitar todos os valores falsy, o || continua sendo a escolha certa.
Dá para combinar nullish coalescing com optional chaining?
Dá sim, e essa dupla é super comum. user?.settings?.theme ?? 'light' percorre a cadeia com segurança, devolve undefined se algo no meio do caminho não existir e, então, aplica 'light' como padrão. Os dois operadores foram lançados juntos no ES2020 justamente pensando nesse uso.
Para que serve o operador ??= ?
a ??= b atribui b a a somente quando a está como null ou undefined. É a atribuição lógica nullish — um atalho para a = a ?? b, mas com short-circuit: se a já tem valor, o lado direito nem chega a ser avaliado. Muito útil para preencher defaults que faltam em um objeto de opções.