Operador Spread

O que é o Operador Spread?

operador spread foi adicionado na versão ES6 (ECMAScript 2015) do Javascript, ele é uma nova sintaxe que permite que nós desenvolvedores adicionemos itens a arrays de forma rápida.

Além da possibilidade de combinar arrays, objetos, ou quem sabe espalhar um array dentro dos argumentos de uma função.

Para usa-lo, precisamos fazer o uso das reticências, que são os famosos 3 pontinhos (...), de modo a para expandir, adicionar ou fazer uma cópia, sua sintaxe é:

...array

Este operador é muito útil para tarefas rotineiras do Javascript, como por exemplo:

  • Copiar uma Matriz (Array, Objeto),
  • Concatenar ou combinar arrays,
  • Usar funções matemáticas,
  • Usar uma matriz com argumentos,
  • Adicionar um novo item a lista,
  • Adicionar um novo estado em React,
  • Combinar novos elementos,
  • Converter uma NodeList em um Array.

Trabalhando com Spread Operator

Agora que você já sabe os objetivos do spread operator (...), chegou o momento de usa-lo na prática.

Observe abaixo que temos dois objetos onde queremos coloca-los dentro de um único objeto, ou seja, nós queremos fazer a concatenação por meio do spread operator:

const objetoUm = {letras: "A,B,C,D,E"};
const objetoDois = {numeros: "1,2,3,4,5"};

const objetos = {...objetoUm,...objetoDois};

console.log(objetos);//{letras: "A,B,C,D,E", numeros: "1,2,3,4,5"}

Observe que sem o spread operator, o JS iria concatenar dois objetos aninhados dentro de um único objeto:

const objetos = {objetoUm,objetoDois};

//Resultado:

/*
{
objetoDois: {
numeros: "1,2,3,4,5"
},
objetoUm: {
letras: "A,B,C,D,E"
}
}
*/

Spread Operator funciona como um Join(',')?

É importante você saber que quando usamos o spread operator em conjunto com um array, é como se "usássemos" o método join() passando uma vírgula como argumento:

const meuArray = ['micilini', 'roll', true, 27];

console.log(...meuArray);//"micilini", "roll", true, 27

Observe que no caso do console.log acima, está retornando os dados específicos, ou seja, diferente do join() em que o retorno é sempre uma string, o retorno do spread é uma concatenação de valores.

Isso significa que não podemos usar o spread dentro de uma variável comum, pois como vimos anteriormente, uma variável só pode armazenar um único tipo de valor, diferente de objetos e arrays:

const meuArray = ['micilini', 'roll', true, 27];

let variavel = ...meuArray;//Error, pois estamos tentando armazenar mais de um tipo de valor dentro de uma única variável comum

let variavelDois = {...meuArray};//{0: "micilini", 1: "roll", 2: true, 3: 27}

let variavelTres = [...meuArray];//["micilini", "roll", true, 27]

Fazendo a cópia de um Array

Podemos usar o spread operator de modo a copiar uma matriz para outra, vejamos como tudo isso funciona abaixo:

Vamos supor que você queira fazer uma copia de um array para outro, como vimos anteriormente, você pode fazer isso facilmente usando o operador de atribuição da seguinte forma:

const frutas = ['banana', 'pera', 'uva', 'abacaxi'];
const maisFrutas = frutas;

console.log(maisFrutas);//["banana", "pera", "uva", "abacaxi"]

O problema é que nesse caso, você não faz bem uma nova cópia do array, até porque, se alteramos o valor do índice 0 do array frutas, o valor do índice 0 do array maisFrutas também será modificado:

const frutas = ['banana', 'pera', 'uva', 'abacaxi'];
const maisFrutas = frutas;

console.log(maisFrutas);//["banana", "pera", "uva", "abacaxi"]

frutas[0] = 'SALADA';

console.log(maisFrutas);//["SALADA", "pera", "uva", "abacaxi"]

Nesse caso, podemos dizer que o maisFrutas não fez uma cópia dos elementos existentes no frutas, mas sim uma referência, de modo que todas as alterações feitas dentro do frutas sejam surtidas também dentro do maisFrutas.

Ok, então como eu faço para que o JS faça uma cópia verdadeira e não uma referência?

Simples, para isso usamos o SPREAD:

const frutas = ['banana', 'pera', 'uva', 'abacaxi'];
const maisFrutas = [...frutas];//SPREAD OPERATOR, nova cópia

console.log(maisFrutas);//["banana", "pera", "uva", "abacaxi"]

frutas[0] = 'SALADA';

console.log(maisFrutas);//["banana", "pera", "uva", "abacaxi"]

Dessa forma, toda e qualquer modificação feito no antigo array não surtirá efeito na cópia.

Combinando Arrays

Com o spread operator, também podemos combinar mais de um array em um único array, vejamos:

const letras = ['a', 'b', 'c'];

const letrasDois = ['d', 'e', 'f'];

const resultado = [...[...letras, ...letrasDois]];

console.log(resultado);//["a", "b", "c", "d", "e", "f"]

Outro exemplo de concatenação de arrays:

const meuArray = ['Micilini', 'Roll', 27];
const seuArray = [true, 12, '🐻'];

const nossoArray = [...meuArray,...seuArray];

console.log(...nossoArray) //"Micilini", "Roll", 27, true, 12, "🐻"

Argumentos de uma Função

Podemos usar o spread operator, como argumentos de uma função quando temos um array.

Por exemplo, vamos supor que temos uma função que recebe dois parâmetros, que são nome e idade:

function montaMensagem(nome, idade){
console.log('Olá: ' + nome + ', você tem ' + idade + ' anos de idade =)');
}

E que também temos um array que só possuí dois itens, que são:

const meuArray = ['Micilini', 26];

Supondo que queremos enviar esses dois itens para dentro daquela função, existem duas maneiras de se fazer isso.

A primeira delas envolve passar os valores de cada um dos itens pelo índice, até porque nosso array sempre terá dois índices, não é verdade?

montaMensagem(meuArray[0], meuArray[1]);//"Olá: Micilini, você tem 26 anos de idade =)"

A segunda envolve a utilização do spread operator, onde só precisamos passar o array para a função:

montaMensagem(...meuArray);

Você se lembra que quando usamos o spread operator dentro de um console.log é como se tivéssemos usando o join(',')?

Então, quando passamos o array em conjunto com o spread operator, é como se tivéssemos passando somente os valores, dessa forma:

montaMensagem(...meuArray);

//É igual a:

montaMensagem('Micilini', 26);

É por esse motivo que o spread operator funciona muito bem no envio de argumentos para uma função.

Adicionando um item a lista

Também podemos adicionar alguns itens usando o spread operator, veja como é fácil:

const frutas = ['maça','kiwi','banana'];
const maisFrutas = ['melancia', 'abacate', ...frutas];

console.log(maisFrutas); //["melancia", "abacate", "maça", "kiwi", "banana"]

Combinando Objetos

Além dos arrays, também podemos realizar a combinação de objetos por meio do spread operator, vejamos:

const objetoUm = {nome: "Micilini"};
const objetoDois = {site: "https://micilini.com"};
const objetoTres = {...objetoUm, ...objetoDois, usaHttps: true};

console.log(objetoTres);// { nome: "Micilini", site: "https://micilini.com", usaHttps: true }

Spread Operator com matrizes aninhadas

É importante ressaltar que o spread operator consegue fazer uma cópia apenas do primeiro nível de aninhamento de uma matriz.

Observe:

const objeto = [['a'], ['b'], ['c']];

const novoObjeto = [...objeto];//copia

console.log(novoObjeto);//[["a"], ["b"], ["c"]]

objeto[0][0] = 'SALADA';

console.log(novoObjeto);//[["a"], ["b"], ["c"]]

Na Matriz acima nós temos um array dentro da variável objeto que possuí dois níveis de aninhamento.

Nesse caso quando fizemos uma cópia  para uma outra variável, todos os aninhamentos serão tratados como uma referência e não como uma cópia, tanto é que quando alteramos o índice pela variável objeto, essa mesma alteração também surtiu efeito no novoObjeto.

E como realizar uma cópia profunda?

Bem, apesar de não termos chegado nessa parte ainda, você pode fazer o uso dos métodos do JSON para isso:

const objeto = [['a'], ['b'], ['c']];

const novoObjeto = JSON.parse(JSON.stringify(objeto));

console.log(novoObjeto);//[["a"], ["b"], ["c"]]

objeto[0][0] = 'SALADA';

console.log(novoObjeto);//[["a"], ["b"], ["c"]]

Conclusão

Neste conteúdo nós vimos o quão útil o spread operator pode ser no dia a dia do desenvolvedor, permitindo combinar arrays, adicionar novos itens e fazer cópias verdadeiras.

Com uma sintaxe fácil, esse operador economiza tempo na codificação, de forma a evitar a utilização de alguns métodos de cópia e concatenação existentes nos arrays e objetos.

Até a próxima jornada 😀