Desenvolvimento

25 out, 2018

Descomplicando JavaScript Destructuring – Objetos

Publicidade

É essencial que nosso código seja limpo, conciso e, principalmente, que funcione. Apesar de JavaScript ser uma das linguagens de programação mais usadas na atualidade, em uma enorme variedade de projetos em diversas áreas, como back-end, front-end, IoT, VR e mobile, ela é uma das linguagens que mais nos prega pegadinhas na hora de usar.

Há um tempo o JavaScript recebeu alguns poderosos recursos, que merecem ser notados e que podem ser usados para que nosso código seja mais limpo, mais conciso e até mais seguro, como template literals, destructuring, arrow functions, classes e spread operator.

Neste artigo vamos entender o poder e a facilidade que a funcionalidade destructuring pode trazer ao nosso código e às nossas aplicações. Mas, antes de entender como é importante, entender o porquê. Se você é familiarizado e/ou programa em TypeScript, usa frameworks como Angular, Vue.js, React, você já conhece destructuring. Porém, há uma grande possibilidade de você aprender coisas novas por aqui.

Aqui estou assumindo que você já conhece um pouco de JavaScript, então não explicarei alguns pontos base da linguagem, assumindo que você já os conhece, ok? Precisamos também notar que, dependendo da versão do seu browser, se for uma versão antiga, alguns dos snippets apresentados aqui podem não funcionar.

Caso aconteça, recomendo atualizar seu browser (manter o software de seu computador sempre atualizado ajuda a prevenir brechas de segurança). Você também pode rodar os snippets no Codepen ou no seu editor online de JavaScript preferido.

Por que usar Destructuring?

Vamos imaginar que fizemos uma requisição para um recurso de inteligência artifical capaz de medir o sentimento de uma determinada frase. Esse recurso nos devolve um objeto com a propriedade sentimentos e esse objeto é um objeto que contém o nome do sentimento como chave e o valor é a probabilidade deste sentimento estar presente, em %. Como podemos fazer para mostrar a probabilidade de cada sentimento presente nesta resposta?

const resposta = {
  usuario: 'Claudiney Junior',
  canal: 'whatsapp',
  felicidade: 80.34,
  tristeza: 1.43,
  euforia: 60.32,
};

console.log('Olá, meu nome é ' + resposta.usuario);
console.log('A probabilidade de felicadade no texto é de: ' + resposta.felicidade);
console.log('A probabilidade de tristeza no texto é de: ' + resposta.tristeza);
console.log('A probabilidade de euforia no texto é de: ' + resposta.euforia);

// Olá, meu nome é Claudiney Junior
// A probabilidade de felicadade no texto é de: 80.34
// A probabilidade de tristeza no texto é de: 1.43
// A probabilidade de euforia no texto é de: 60.32

O exemplo acima vai funcionar sem problemas, mas vejam a quantidade de código que temos que escrever para alcançar o objetivo desejado. Escrever o código assim nos faz ter que escrever diversas vezes resposta.sentimentos, o que pode nos levar a erros de digitação e muito mais código. Pode parecer pouco, mas com o destructuring nós podemos fazer a mesma coisa com muito menos código.

O que é destructuring?

Destructuring é basicamente quebrar uma estrutura complexa em partes mais simples. Por estrutura complexa, na maioria das vezes podemos considerar como sendo um array ou um objeto. Neste artigo trataremos somente de objetos. Trarei pra vocês a aplicação de destructuring em arrays em um próximo artigo.

O destructuring pode ser usado tanto para declarar variáveis quanto para atribuir valores a variáveis.

Então como ficaria o exemplo anterior com destructuring?

const resposta = {
  usuario: 'Claudiney Junior',
  canal: 'whatsapp',
  felicidade: 80.34,
  tristeza: 1.43,
  euforia: 60.32,
};

const { usuario, felicidade, tristeza, euforia } = resposta;

console.log('Olá, meu nome é ' + usuario);
console.log('A probabilidade de felicadade no texto é de: ' + felicidade);
console.log('A probabilidade de tristeza no texto é de: ' + tristeza);
console.log('A probabilidade de euforia no texto é de: ' + euforia);


// Olá, meu nome é Claudiney Junior
// A probabilidade de felicadade no texto é de: 80.34
// A probabilidade de tristeza no texto é de: 1.43
// A probabilidade de euforia no texto é de: 60.32

No exemplo acima podemos ver que “quebramos” o objeto resposta em diversas partes menores, declarando variáveis com o mesmo nome das propriedades deste objeto, ok?

Mas e se eu já tivesse declarado variáveis com estes valores e quisesse re-atribuir estes valores? Bom, o destructuring também pode me ajudar nessa tarefa.

let usuario = 'John Doe';
let canal = 'facebook';
let felicidade = 0.0;

const resposta = {
  usuario: 'Claudiney Junior',
  canal: 'whatsapp',
  felicidade: 80.34,
  tristeza: 1.43,
  euforia: 60.32,
};

({ usuario, canal, felicidade, tristeza, euforia } = resposta);

console.log('Olá, meu nome é ' + usuario);
console.log('A probabilidade de felicadade no texto é de: ' + felicidade);
console.log('A probabilidade de tristeza no texto é de: ' + tristeza);
console.log('A probabilidade de euforia no texto é de: ' + euforia);

No código acima, o destructuring está fazendo duas coisas distintas. A primeira é declarar novas variáveis tristeza e euforia e atribuir a elas o valor dos atributos, de mesmo nome, do objeto resposta. A segunda é re-atribuir o valor de variáveis já declaradas, como usuario, canal e felicidade.

Repare que neste exemplo tive que usar ( ) em volta da expressão. Se eu não tivesse colocado o destructuring, seria tratado como um statement e isto não pode ocorrer do lado esquerdo de uma expressão de atribuição.

Valores default

Mas nem sempre podemos garantir que o objeto que estamos “quebrando” terá todos os atributos que estamos declarando ou re-atribuindo fora. Por isso temos um recurso muito interessante para previnir o aparecimento de erros inesperados em tempo de execução.

Imagine que você está consumindo um serviço que você sempre espera um determinado payload na resposta. Tudo rodando em produção, bonitinho, até que um dia o serviço que você está consumindo não manda mais uma determinada propriedade, não importa o motivo. Você pode fazer com que seu serviço deixe de funcionar.

Para que isso não aconteça, pode ser interessante declarar valores padrão para seus objetos. E como faríamos isso?

O exemplo abaixo foi retirado do contexto de um servidor express recebendo uma requisição. Ele recebe os parâmetros req e res, que são, respectivamente, o objeto de requisição e o objeto de resposta.

const get = (req, res) => {
  const { studentId } = req.params;
  const { name, year = 2018 } = req.query;
  if (studentId) {
    findOne(); // Acha 1 estudante pelo id dele rota GET | /students/:studentId
  }
  findAll(year, name); // Passa o nome e ano como filtro. Se nenhum ano for passado considera como default 2018
}

Eu uso bastante o destructuring nesses filtros de API, pois ele me faz economizar bastante código. Neste exemplo eu posso usar a mesma função para o endpoint /students e também para o /students/:studentId.

Se houver no objeto req.params a propriedade studentId, eu sei que eu só preciso achar um único estudante.

Se não houver a propriedade studentId, eu sei que preciso achar todos os alunos da minha base, mas me foi passado um requisito que, por padrão, só devo mostrar os alunos matriculados no ano de 2018. Então eu posso definir um valor padrão, 2018, para a propriedade year, retirada do objeto req.query.

Usando nomes diferentes

Nem sempre o nome que vem no objeto que vamos “dissecar” é o melhor para a semântica de nossa aplicação. Também temos um pequeno atalho para usar o destructuring já atribuindo um novo nome à propriedade que eu quero.

const pessoa = {
  nome: 'Claudiney Junior',
  cpf: '123.456.789-03',
  city: 'São Paulo'
};

const { nome, cpf: id, city: cidade, birthday: nascimento = '24/10/1988' } = pessoa;

console.log(`Olá, eu sou o ${nome}, meu id é ${id}, sou de ${cidade} e nasci em ${nascimento}`);

A sintaxe é muito simples. nomeOriginal: novoNome, e eu consigo renomear a propriedade. Hoje em dia quase ninguém desenvolve sozinho, então devemos observar a importância de um código semântico e limpo, usar o nome correto na hora correta é um dom.

No exemplo acima eu renomeei a propriedade city para cidade, a cpf para id e a birthday para nascimento. Vejam que a propriedade birthday não existia, e por isso eu declarei um valor default pra ela, combinando dois recursos que vimos por aqui.

Nested Object Destructuring

Embora o nome possa assustar, aqui estou falando de destructuring em objetos “aninhados”. É uma coisa bem comum que haja um objeto dentro de outro e que eu queira separar este objeto grande em pequenas partes.

const pessoa = {
  nome: 'Claudiney Junior',
  cpf: '123.456.789-03',
  city: 'São Paulo',
  notas: {
    matematica: 10,
    fisica: 10,
    educaoFisica: 4
  }
};

const { nome, cpf, notas: { matematica, fisica, educaoFisica, geografia = 0 }} = pessoa;

console.log(`O aluno ${nome} de CPF: ${cpf} tem as seguintes notas:`);
console.log(`Matemática: ${matematica}`);
console.log(`Física: ${fisica}`);
console.log(`Educação Física: ${educaoFisica}`);
console.log(`Geografia: ${geografia}`);

No exemplo acima nós temos o objeto notas dentro do objeto pessoa, e eu quero pegar as notas desta pessoa. Eu consigo as notas de Matemática, Física e Educacao Fisica. Porém, ela não cursou Geografia, por ser opcional – o que eu já previa e atribui o valor de 0 a esta disciplina.

Conclusão

O destructuring é bem conhecido por desenvolvedores dos mais famosos frameworks JavaScript da atualidade, porém eu queria passar para as pessoas que não conhecem o recurso ainda, ou mesmo para as que conhecem, quem sabe aprender uma coisa ou outra diferente.

Menos código na maioria das vezes significa um código mais limpo e mais organizado, portanto, tente usar o destructuring e veja os maravilhosos resultados. Em breve posto a Parte 02 com Arrays.

Para este artigo, me inspirei e traduzi algumas partes deste artigo aqui.

Espero ter ajudado!