segunda-feira, 16 de maio de 2022
Operador de Encadeamento Opcional (?.) (Optional Chaining) em Javascript
O Operador de Encadeamento Opcional (
?.), ou Optional Chaining, é um operador do Javascript que permite acessar propriedades de um determinado objeto sem fazer grandes verificações explícitas (usando um
if, ou um operador condicional ternário (
condicao ? expr1 : expr2), por exemplo) sobre a existência do próprio objeto. E isso é incrível principalmente porque é bem comum termos diversos objetos encadeados, onde alguns deles podem ser
nullou
undefinedem algum estado de certa aplicação.
Problema inicial
Para ficar mais claro, vamos ver um exemplo bem simples:
Considere que, em algum estado da minha aplicação, teremos um objeto usuario que terá outro objeto encadeado chamado contato e que esse terá algumas propriedades de contato, como telefone, por exemplo:
const usuario = {contato: {telefone: '9999-9999'}};
Mas vamos supor que esses dados de contato não estejam disponíveis em um estado inicial, então meu objeto usuario estará vazio:
const usuario = {};
Apenas com o que temos acima, não podemos saber em qual estado nossa aplicação está. Logo, não conseguiremos saber se o objeto contato existe no objeto usuario. O que acontece se tentarmos acessar as propriedades desse objeto em diferentes estados então?
Bem, se o objeto contato está no usuario como o esperado, então funcionará corretamente:
const usuario = {contato: {telefone: '9999-9999'}};console.log('Telefone:', usuario.contato.telefone);// ✅ Funciona
Mas se o objeto contato ainda não está no usuario, a história muda:
const usuario = {};console.log('Telefone:', usuario.contato.telefone);// ❌ Uncaught TypeError:// Cannot read properties of undefined (reading 'telefone')
O objeto contato ainda não foi definido (
undefined) no objeto usuario, logo não podemos acessar suas propriedades.
Utilizando o operador de encadeamento opcional
Como já dito, há diversas formas de resolver isso, mas o operador de encadeamento opcional deixa tudo bem limpo e simples:
console.log('Telefone:', usuario.contato?.telefone);// here ^
- Se o
usuario.contato
existe, então conseguiremos acessar a propriedadetelefone
normalmente e exibir o dado. - Já se o
usuario.contato
fornull
ouundefined
, então o operador de encadeamento opcional retornaráundefined
e nem tentará acessar a propriedadetelefone
.
Possibilidades
Além de objetos encadeados, podemos usar o operador em funções, e até mesmo arrays:
-
Funções:
const foto = usuario.exibirFoto?.();Só executará a função exibirFoto caso ela não seja
null
ouundefined
. Caso contrário, foto seráundefined
. -
Arrays:
const usuario = {contatos: [{ telefone: '9999-9999' }, { telefone: '8888-8888' }]};const primeiroTelefone = usuario.contatos?.[0]?.telefone;Aqui podemos ver duas possibilidades:
- Em
contatos?.
, verificamos se o array contatos já existe no objeto usuario, antes de prosseguirmos acessando o resto da cadeia (que nesse caso é tentar acessar o primeiro elemento do array). - Se
contatos?.
nos retornou o array (ao invés deundefined
), como esperado, então prosseguimos e verificamos se o primeiro elemento existe:[0]?.
. - Caso tenhamos passado por ambos os operadores de encadeamento opcional, então conseguimos acessar a propriedade telefone normalmente.
Caso não, teremos
undefined
como valor da constante primeiroTelefone.
- Em