06 de março de 2024 • 9 min de leitura
Como usar operadores ternários, nullish e optional chaining no JavaScript
Aprenda a usar os operadores ternários, nullish e optional chaining para simplificar o código JavaScript e lidar com valores, condições e propriedades de forma mais eficiente.
O JavaScript é uma linguagem de programação que oferece diversas formas de escrever código de forma concisa, elegante e expressiva. Neste artigo, vamos aprender sobre três operadores que podem facilitar a nossa vida na hora de lidar com valores, condições e propriedades: os operadores ternários, nullish e optional chaining.
O que são operadores ternários?
Os operadores ternários são uma forma de escrever uma expressão condicional que retorna um valor dependendo de uma condição. A sintaxe é a seguinte:
condição ? valor1 : valor2
Onde:
condição
é uma expressão que pode ser avaliada como verdadeira ou falsavalor1
é o valor que será retornado se a condição for verdadeiravalor2
é o valor que será retornado se a condição for falsa
Por exemplo, suponha que temos uma variável idade
que armazena a idade de uma pessoa. Podemos usar um operador ternário para atribuir uma mensagem à variável status
dependendo da idade:
let idade = 18;
let status = idade >= 18 ? 'Maior de idade' : 'Menor de idade';
console.log(status); // Maior de idade
O operador ternário é equivalente a escrever um bloco if...else
, mas de forma mais compacta e legível. Por exemplo, o código acima poderia ser escrito assim:
let idade = 18;
let status;
if (idade >= 18) {
status = 'Maior de idade';
} else {
status = 'Menor de idade';
}
console.log(status); // Maior de idade
Quais são as vantagens de usar operadores ternários?
Os operadores ternários podem trazer algumas vantagens para o nosso código, como:
- Reduzir o número de linhas e caracteres
- Melhorar a clareza e a intenção do código
- Evitar o uso de variáveis desnecessárias ou repetidas
- Facilitar a atribuição de valores a variáveis ou propriedades
- Permitir o uso de expressões condicionais em locais onde não seria possível usar blocos
if...else
, como em parâmetros de funções, retornos de funções, templates strings, etc.
Por exemplo, podemos usar um operador ternário para definir o valor de um parâmetro de uma função de forma dinâmica, dependendo de uma condição:
function saudar(nome, hora) {
let periodo = hora < 12 ? 'Bom dia' : 'Boa tarde';
console.log(`${periodo}, ${nome}!`);
}
saudar('Ana', 10); // Bom dia, Ana!
saudar('Bruno', 14); // Boa tarde, Bruno!
O que é o operador nullish?
O operador nullish (??
) é um operador lógico que retorna o seu operando da direita se o operando da esquerda for null
ou undefined
, e o operando da esquerda caso contrário. A sintaxe é a seguinte:
valor1 ?? valor2
Onde:
valor1
é o valor que será retornado se não fornull
ouundefined
valor2
é o valor que será retornado sevalor1
fornull
ouundefined
Por exemplo, suponha que temos uma função que recebe um objeto com as propriedades nome
e sobrenome
de uma pessoa, e queremos retornar o nome completo da pessoa. Podemos usar o operador nullish para definir um valor padrão para as propriedades que podem ser null
ou undefined
, como por exemplo, uma string vazia:
function nomeCompleto(pessoa) {
let nome = pessoa.nome ?? '';
let sobrenome = pessoa.sobrenome ?? '';
return `${nome} ${sobrenome}`.trim();
}
console.log(nomeCompleto({ nome: 'Alice', sobrenome: 'Silva' })); // Alice Silva
console.log(nomeCompleto({ nome: 'Bob' })); // Bob
console.log(nomeCompleto({ sobrenome: 'Costa' })); // Costa
console.log(nomeCompleto({})); // (string vazia)
Qual é a diferença entre o operador nullish e o operador lógico OR (||
)?
O operador lógico OR (||
) é um operador que retorna o seu operando da direita se o operando da esquerda for um valor falso (false
, 0
, ''
, null
, undefined
ou NaN
), e o operando da esquerda caso contrário. A sintaxe é a seguinte:
valor1 || valor2
O operador nullish é semelhante ao operador OR, mas tem uma diferença importante: ele só considera os valores null
e undefined
como falsos, e não os outros valores. Isso pode ser útil quando queremos definir um valor padrão para uma variável ou propriedade, mas não queremos ignorar os valores que podem ser válidos, mas que são falsos para o operador OR, como 0
, ''
ou false
.
Por exemplo, suponha que temos uma função que recebe um objeto com as propriedades nome
e ativo
de um usuário, e queremos retornar uma mensagem de boas-vindas ou de despedida dependendo do status do usuário. Se usarmos o operador OR para definir um valor padrão para a propriedade ativo
, podemos ter um problema, pois o valor false
será ignorado e substituído pelo valor padrão, que é true
. Veja:
function mensagem(usuario) {
let nome = usuario.nome ?? 'Visitante';
let ativo = usuario.ativo || true; // usando o operador OR
return ativo ? `Olá, ${nome}!` : `Até logo, ${nome}!`;
}
console.log(mensagem({ nome: 'Carlos', ativo: true })); // Olá, Carlos!
console.log(mensagem({ nome: 'Daniela', ativo: false })); // Olá, Daniela! (errado, deveria ser Até logo, Daniela!)
console.log(mensagem({ nome: 'Eduardo' })); // Olá, Eduardo!
console.log(mensagem({ ativo: false })); // Olá, Visitante! (errado, deveria ser Até logo, Visitante!)
console.log(mensagem({})); // Olá, Visitante!
Para resolver esse problema, podemos usar o operador nullish, que vai respeitar o valor false
e só vai usar o valor padrão se a propriedade for null
ou undefined
. Veja:
function mensagem(usuario) {
let nome = usuario.nome ?? 'Visitante';
let ativo = usuario.ativo ?? true; // usando o operador nullish
return ativo ? `Olá, ${nome}!` : `Até logo, ${nome}!`;
}
console.log(mensagem({ nome: 'Carlos', ativo: true })); // Olá, Carlos!
console.log(mensagem({ nome: 'Daniela', ativo: false })); // Até logo, Daniela! (correto)
console.log(mensagem({ nome: 'Eduardo' })); // Olá, Eduardo!
console.log(mensagem({ ativo: false })); // Até logo, Visitante! (correto)
console.log(mensagem({})); // Olá, Visitante!
O que é o operador optional chaining?
O operador optional chaining (?.
) é um operador que permite acessar as propriedades de um objeto que podem ser null
ou undefined
, sem gerar um erro. A sintaxe é a seguinte:
objeto?.propriedade
Onde:
objeto
é o objeto que queremos acessarpropriedade
é a propriedade que queremos acessar
Se o objeto for null
ou undefined
, o operador optional chaining vai retornar undefined
, em vez de lançar um erro do tipo TypeError
. Se o objeto não for null
ou undefined
, o operador optional chaining vai funcionar como o operador de acesso à propriedade (.
).
Por exemplo, suponha que temos uma função que recebe um objeto com as propriedades nome
, email
e telefone
de um cliente, e queremos retornar o contato preferido do cliente. Se usarmos o operContinuando o artigo:
ador optional chaining, podemos ter um problema, pois se o objeto for null
ou undefined
, vamos receber um erro do tipo TypeError: Cannot read property 'propriedade' of null (or undefined)
. Veja:
function contatoPreferido(cliente) {
let nome = cliente.nome ?? 'Cliente';
let email = cliente.email;
let telefone = cliente.telefone;
if (email) {
return `O contato preferido de ${nome} é o email: ${email}`;
} else if (telefone) {
return `O contato preferido de ${nome} é o telefone: ${telefone}`;
} else {
return `Não temos o contato de ${nome}`;
}
}
console.log(contatoPreferido({ nome: 'Fernanda', email: 'fernanda@gmail.com', telefone: '(11) 99999-9999' })); // O contato preferido de Fernanda é o email: fernanda@gmail.com
console.log(contatoPreferido({ nome: 'Gabriel', telefone: '(11) 88888-8888' })); // O contato preferido de Gabriel é o telefone: (11) 88888-8888
console.log(contatoPreferido({ nome: 'Helena' })); // Não temos o contato de Helena
console.log(contatoPreferido(null)); // TypeError: Cannot read property 'nome' of null
Para resolver esse problema, podemos usar o operador optional chaining, que vai evitar o erro e retornar undefined
se o objeto for null
ou undefined
. Veja:
function contatoPreferido(cliente) {
let nome = cliente?.nome ?? 'Cliente';
let email = cliente?.email;
let telefone = cliente?.telefone;
if (email) {
return `O contato preferido de ${nome} é o email: ${email}`;
} else if (telefone) {
return `O contato preferido de ${nome} é o telefone: ${telefone}`;
} else {
return `Não temos o contato de ${nome}`;
}
}
console.log(contatoPreferido({ nome: 'Fernanda', email: 'fernanda@gmail.com', telefone: '(11) 99999-9999' })); // O contato preferido de Fernanda é o email: fernanda@gmail.com
console.log(contatoPreferido({ nome: 'Gabriel', telefone: '(11) 88888-8888' })); // O contato preferido de Gabriel é o telefone: (11) 88888-8888
console.log(contatoPreferido({ nome: 'Helena' })); // Não temos o contato de Helena
console.log(contatoPreferido(null)); // Não temos o contato de Cliente
Como usar o operador optional chaining com arrays e funções?
O operador optional chaining também pode ser usado para acessar os elementos de um array ou chamar uma função que podem ser null
ou undefined
, sem gerar um erro. A sintaxe é a seguinte:
array?.[indice]
funcao?.(argumentos)
Onde:
array
é o array que queremos acessarindice
é o índice do elemento que queremos acessarfuncao
é a função que queremos chamarargumentos
são os argumentos que queremos passar para a função
Se o array ou a função forem null
ou undefined
, o operador optional chaining vai retornar undefined
, em vez de lançar um erro do tipo TypeError
. Se o array ou a função não forem null
ou undefined
, o operador optional chaining vai funcionar como o operador de acesso ao elemento ([]
) ou o operador de chamada de função (()
).
Por exemplo, suponha que temos uma função que recebe um array de números e uma função de callback, e queremos aplicar a função de callback a cada elemento do array e retornar um novo array com os resultados. Podemos usar o operador optional chaining para evitar um erro se o array ou a função de callback forem null
ou undefined
. Veja:
function mapear(array, callback) {
let resultado = [];
for (let i = 0; i < array?.length; i++) {
let elemento = array?.[i];
let novoElemento = callback?.(elemento);
resultado.push(novoElemento);
}
return resultado;
}
console.log(mapear([1, 2, 3], x => x * 2)); // [2, 4, 6]
console.log(mapear(null, x => x * 2)); // []
console.log(mapear([1, 2, 3], null)); // [undefined, undefined, undefined]
console.log(mapear(null, null)); // []
Conclusão
Neste artigo, aprendemos sobre três operadores que podem nos ajudar a escrever código mais conciso, elegante e expressivo no JavaScript: os operadores ternários, nullish e optional chaining. Vimos como eles funcionam, quais são as suas vantagens e como usá-los em diferentes situações. Esperamos que você tenha gostado e que possa aplicar esses conhecimentos nos seus projetos.