<h2>Optional Chaining (?.)</h2>
<p>O Optional Chaining é um operador que permite acessar propriedades profundas de um objeto sem necessidade de validações intermináveis. Introduzido no ES2020, ele resolve um problema clássico: quando você tenta acessar uma propriedade de um valor nulo ou indefinido, JavaScript lança um erro. Com <code>?.</code>, a operação retorna <code>undefined</code> graciosamente em vez de quebrar sua aplicação.</p>
<p>O operador funciona em três contextos: acesso a propriedades (<code>obj?.prop</code>), chamadas de método (<code>func?.()</code>), e acesso a índices (<code>arr?.[0]</code>). Quando o valor antes do <code>?.</code> é <code>null</code> ou <code>undefined</code>, toda a cadeia de avaliação para e retorna <code>undefined</code>. Caso contrário, continua normalmente.</p>
<pre><code class="language-javascript">const usuario = {
perfil: {
endereco: {
cidade: "São Paulo"
}
}
};
// Sem optional chaining (arriscado)
const cidade = usuario.perfil.endereco.cidade; // "São Paulo"
// const rua = usuario.perfil.endereco.rua; // undefined (OK)
// const cep = usuario.perfil.telefone.cep; // TypeError!
// Com optional chaining (seguro)
const cep = usuario?.perfil?.endereco?.cep; // undefined
const telefone = usuario?.contato?.telefone; // undefined
const metodo = usuario?.getInfo?.(); // undefined se não existir
// Com arrays
const items = usuario?.pedidos?.[0]?.id; // undefined se pedidos não existir</code></pre>
<h3>Quando usar Optional Chaining</h3>
<p>Use quando trabalhar com dados de APIs, respostas assincronamente carregadas ou estruturas que você não controla totalmente. É especialmente útil em requisições HTTP onde a resposta pode ter propriedades ausentes. Evite usar quando a propriedade <em>deve</em> existir — nesse caso, deixe o erro vir para identificar o problema real.</p>
<h2>Nullish Coalescing (??)</h2>
<p>O Nullish Coalescing, também do ES2020, é um operador lógico que retorna o operando à direita apenas quando o da esquerda é <code>null</code> ou <code>undefined</code>. Diferente do <code> | | </code>, ele não trata valores falsos como vazios: <code>0</code>, <code>""</code> e <code>false</code> são valores válidos.</p> <p>Esse detalhe é crucial em programação real. Se você usa <code>||</code> e recebe <code>0</code> como quantidade de itens ou <code>false</code> como flag booleana, inadvertidamente substituirá esses valores legítimos pelo padrão. O <code>??</code> resolve isso elegantemente.</p> <pre><code class="language-javascript">// Problema com ||
const quantidade = 0;
const valor = quantidade || 10; // 10 (incorreto! 0 é válido)
// Solução com ??
const valor2 = quantidade ?? 10; // 0 (correto!)
// Com strings
const nome = "" ?? "Anônimo"; // "" (mantém string vazia)
const nome2 = "" || "Anônimo"; // "Anônimo" (substitui)
// Em APIs
const config = {
timeout: 0,
retries: false,
debug: undefined
};
const timeout = config.timeout ?? 5000; // 0
const retries = config.retries ?? 3; // false
const debug = config.debug ?? true; // true</code></pre>
<h3>Combinando com Optional Chaining</h3>
<p>A combinação <code>?.</code> com <code>??</code> é poderosa. Você acessa a propriedade seguramente e fornece um padrão se ela não existir:</p>
<pre><code class="language-javascript">const resposta = {
dados: { contador: 0 }
};
const contador = resposta?.dados?.contador ?? 100; // 0
const prioridade = resposta?.config?.nivel ?? "média"; // "média"</code></pre>
<h2>Logical Assignment Operators</h2>
<p>Os operadores de atribuição lógica (introduzidos no ES2021) combinam operadores lógicos com atribuição: <code>&&=</code>, <code> | | =</code> e <code>??=</code>. Eles atribuem um valor apenas se a condição lógica for satisfeita, evitando código verboso com <code>if</code>.</p> <p><code>||=</code> atribui se o valor é falso (falsy). <code>&&=</code> atribui se o valor é verdadeiro (truthy). <code>??=</code> atribui se é <code>null</code> ou <code>undefined</code>. Cada um tem seu caso de uso, e escolher o correto evita bugs sutis.</p> <pre><code class="language-javascript">// ||= : atribui se falsy
let usuario = null;
usuario ||= { nome: "Padrão" }; // { nome: "Padrão" }
let contador = 0;
contador ||= 10; // 10 (problema: 0 é válido!)
// &&= : atribui se truthy
let config = { ativo: true };
config.ativo &&= false; // false
config.ativo &&= "novo"; // "novo"
let vazio = null;
vazio &&= "novo"; // null (não muda)
// ??= : atribui se null ou undefined (recomendado para padrões)
let valor = 0;
valor ??= 100; // 0 (mantém!)
let resultado = undefined;
resultado ??= "padrão"; // "padrão"
// Caso real: inicializar objeto
const obj = {};
obj.cache ??= [];
obj.cache.push("item"); // inicializa apenas uma vez</code></pre>
<h3>Padrão prático: Configurações com Fallbacks</h3>
<pre><code class="language-javascript">function iniciarApp(opcoes = {}) {
// Padrões seguros e legíveis
opcoes.porta ??= 3000;
opcoes.debug ??= false;
opcoes.timeout ??= 5000;
// Ativar logs apenas se debug é true
opcoes.debug &&= console.log;
// Usar cache apenas se disponível
let dados = opcoes.cache || fetch("/dados");
return opcoes;
}
const config = iniciarApp({ debug: true, porta: 8080 });
// { porta: 8080, debug: true, timeout: 5000 }</code></pre>
<h2>Conclusão</h2>
<p>Esses três recursos modernos resolvem problemas reais de segurança e legibilidade em JavaScript. <strong>Optional Chaining</strong> elimina verificações nulas repetitivas quando navega estruturas profundas. <strong>Nullish Coalescing</strong> fornece padrões sem sobrescrever valores falsos legítimos como <code>0</code> e <code>false</code>. <strong>Logical Assignment</strong> torna código declarativo e evita blocos <code>if</code> desnecessários.</p>
<p>O aprendizado prático é: use <code>?.</code> ao acessar propriedades incertas, <code>??</code> para padrões seguros, e <code>??=</code> para inicializações. Combine-os estrategicamente, e seu código será mais robusto e expressivo. A chave é entender <em>quando</em> cada um é apropriado — não são substitutos uns dos outros, mas complementos em diferentes cenários.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining" target="_blank" rel="noopener noreferrer">MDN Web Docs - Optional Chaining</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing" target="_blank" rel="noopener noreferrer">MDN Web Docs - Nullish Coalescing Operator</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND_assignment" target="_blank" rel="noopener noreferrer">MDN Web Docs - Logical Assignment Operators</a></li>
<li><a href="https://javascript.info/optional-chaining" target="_blank" rel="noopener noreferrer">JavaScript.info - Optional chaining</a></li>
<li><a href="https://github.com/tc39/proposals" target="_blank" rel="noopener noreferrer">TC39 Proposals - ECMAScript 2020-2021</a></li>
</ul>