Desenvolvimento

3 ago, 2017

Desmistificando o destructuring do JavaScript ES6/ES7

Publicidade

As novas especificações do EcmaScript trouxeram uma série de melhorias e recursos adicionais na sintaxe e funcionalidade da linguagem. Uma delas que particularmente gosto e uso bastante, por ajudar a deixar o código mais curto e mais claro, é a possibilidade de fazer destructuring em objetos e arrays.

Entender o que esse recurso faz é simples: ele facilita o acesso a dados dentro de um array ou objeto e a criação de variáveis que contenham esses dados. Porém isso não quer dizer que ele faça pouca coisa. Na verdade, suas aplicações são bastante diversas, e vou tentar contemplar algumas neste post.

Desmistificando o destructuring do JavaScript ES6/ES7

Declaração de variáveis

Imaginemos declarar variáveis para dados dentro do seguinte objeto:

company = {
 name: ‘ACME Corp’,
 address: ‘Nowhere st’,
 products: {
 shirts: {
 colors: [‘red’, ‘green’, ‘blue’]
 },
 socks: {
 colors: [‘cyan’, ‘magenta’, ‘yellow’]
 }
 }
};

Vamos mostrar no console o nome da empresa e as cores de camisetas usando ES5:

var companyName = company.name;
var shirtsColors = company.products.shirts.colors;
console.log(companyName); // 'ACME Corp'
console.log(shirtsColors); // [‘red’, ‘green’, ‘blue’]

Agora vamos ver como ficaria usando ES6:

const { name, products: { shirts: { colors } } } = company
console.log(name); // 'ACME Corp'
console.log(colors); // [‘red’, ‘green’, ‘blue’]

É interessante ver como não é mais necessário escrever múltiplas declarações de variáveis de um mesmo objeto. A nova sintaxe facilita a extração dos dados.

Mas e se eu quiser que o nome da variável seja diferente do nome da propriedade do objeto?

É possível extrair o dado do objeto renomeando a variável que está sendo declarada:

const {
 name: companyName,
 products: { shirts: { colors: shirtsColors } }
} = company
console.log(companyName) // 'ACME Corp'
console.log(shirtsColors) // [‘red’, ‘green’, ‘blue’]

E como evito valores não definidos?

Caso alguma propriedade dentro do objeto em questão possa, em certas ocasiões, não estar declarada, é possível tratar isso atribuindo a ela um valor padrão:

const { products: { shirts: { sizes: shirtsSizes = [] } } } = company
console.log(shirtsSizes) // []

Destructuring de objetos que são argumentos em uma função

Quando uma função recebe um objeto como argumento, é comum que precisemos usar atributos dentro desse objeto para executar comandos dentro da função.

Exemplo usando ES5:

var getShirtsColorsAmount = function (company) {
 colors = company.products.shirts.colors;
return colors.length;
}
getShirtsColorsAmount(company); // 3
Exemplo usando ES6:
const getShirtsColorsAmount = ({ 
 products: { shirts: { colors: { length } } }
}) => length
getShirtsColorsAmount(company) // 3

Renomear e atribuir valor padrão continua valendo:

const getShirtsSizes = ({
 products: { shirts: { sizes: shirtsSizes = [] } }
}) => shirtsSizes
getShirtsSizes(company) // []

Spread operator, aquele dos três pontinhos

Imaginemos o seguinte objeto:

const clothes = {
 pants: { colors: [‘black’, ‘blue’] },
 shirts: { colors: [‘white’, ‘red’] },
 socks: { colors: [‘beige’, ‘gray’] },
}

Digamos que eu queira consumir apenas os dados de roupas que não são calças. Não existe nenhum jeito nativo de fazer isso na especificação antiga. A solução dependeria do caso de uso e poderia ser necessário usar um loop. Porém, com o spread operator isso fica muito fácil:

const { pants, ...rest } = clothes
console.log(rest)
// {
// shirts: { colors: [‘white’, ‘red’] },
// socks: { colors: [‘beige’, ‘gray’] },
// }

Plus a mais: além de auxiliar com o destructuring, o spread operator é útil para clonar e concatenar objetos.

const otherClothes = clothes
console.log(otherClothes)
// {
// pants: { colors: [‘black’, ‘blue’] },
// shirts: { colors: [‘white’, ‘red’] },
// socks: { colors: [‘beige’, ‘gray’] },
// }
const moreClothes = {
 ...clothes,
 shoes: { colors: [‘yellow’, ‘purple’] },
}
console.log(moreClothes)
// {
// pants: { colors: [‘black’, ‘blue’] },
// shirts: { colors: [‘white’, ‘red’] },
// socks: { colors: [‘beige’, ‘gray’] },
// shoes: { colors: [‘yellow’, ‘purple’] },
// }

Destructuring de arrays

Além de objetos, também podemos fazer isso com arrays:

const myArr = [1, 2, 3]
const [a, b, c] = myArr
console.log(b) // 2

Valores default continuam valendo:

const [a, b, c, d = 4] = myArr
console.log(d) // 4

E o spread operator também funciona:

const arr = [1, 2, 3]
const arr2 = [4, 5, 6]
console.log([...arr, ...arr2]) // [1, 2, 3, 4, 5, 6]
const [a, ...rest] = arr
console.log(rest) // [2, 3]

Se você quer experimentar um pouco mais este e outros recursos, o Babel, que é um transpilador de JS (serve para escrevermos código com as especificações novas para plataformas onde elas ainda não são totalmente suportadas) possui uma ferramenta em seu site para isso: http://babeljs.io/repl/

Conclusão

O destructuring possui mais recursos e aplicações mais avançadas, mas com este conteúdo já se tem o necessário para começar a usá-lo e simplificar seu código. Como vimos nos exemplos, ele é bastante útil para facilitar a leitura do código e o acesso a valores que precisamos em determinado contexto. Com pouco esforço, temos a variável que queremos, no lugar que queremos, com o nome e valor que queremos e até tratando valores nulos ou indefinidos.

Qualquer dúvida ou consideração sobre o artigo, por favor deixe nos comentários. Até a próxima (;

***

Este artigo foi publicado primeiramente no blog da Taller.