Vamos aprender como usar os três pontos em nosso código. Depois deste artigo, você não esquecerá a diferença entre eles! 🐱🐱🐱
Definição:
- O spread é o operador que nos permite expandir iteráveis em elementos individuais.
- O resto é o operador que usamos para representar um número indefinido de argumentos em um array .
Ambos são escritos usando os três pontos ...
, mas você verá que é fácil identificar quando é spread e quando é descanso! No final também tem uma boa dica para você!
Operador de propagação
Concatenando matrizes
A propagação nos permite combinar dois ou mais arrays, mantendo uma linguagem concisa e limpa.
Vamos tomar um café? ☕️ Considere os dois arrays abaixo:
const coffee = ['coffee', 'water'];
const spices = ['cinnamon', 'nutmeg', 'cardamom'];
Podemos usar a pasta para misturar os ingredientes em uma única matriz:
const coffeeReady = [...coffee, ...spices];
console.log(coffeeReady)
// output:
// ['coffee', 'water', 'cinnamon', 'nutmeg', 'cardamom'];
Simples! Muito melhor do que escrever item por item de cada um dos dois arrays no form coffeeReady
.
Importante :
1. As alterações coffee
NÃO afetarão coffeeReady
!
Para entender melhor: quando fazemos uma cópia, podemos tanto criar uma nova referência ao valor original ou apenas copiar o valor. Criar uma nova referência é simplesmente criar uma variável que apontará para o mesmo local na memória onde está o valor original .
Se tivéssemos criado uma nova referência, quaisquer alterações coffee
seriam alteradas coffeeReady
e vice-versa. Mas o que fizemos com o spread foi copiar apenas o valor, que por sua vez ficará armazenado em outro local da memória . Assim, alterações em um array não afetarão o outro.
Porém, alguns detalhes podem mudar esse quadro! Isso é porque…
2. A propagação cria apenas uma cópia superficial!
Isso significa que, dependendo dos dados contidos em coffee
, algumas alterações podem sim alterar coffeeReady
! Se coffee
contivesse algum valor não primitivo, o computador teria criado uma referência aos valores na memória. Assim, qualquer alteração em um array afetaria o outro, já que ambos estariam armazenando uma referência para o mesmo local na memória. Veja abaixo:
let a = [1, [2, 3]];
// [2, 3] is an array nested in a, and therefore
// it is a non-primitive value
const b = [4, 5, 6];
let c = [...a, ...b];
console.log(c);
// output: [1, [2, 3], 4, 5, 6]
a[0] = 11;
a[1][0] = 22;
console.log(c);
// output: [1, [22, 3], 4, 5, 6]
Veja acima que a alteração a[0]
não afetou c
, pois alteramos um valor primitivo. Em outras palavras, a[0]
e c
apontam para valores iguais, mas eles estão em locais diferentes na memória. Porém, alterando a[1][0]
modificado c
, pois alteramos o valor para o qual ambos a[1][0]
e c
apontam.
Mesclando objetos
Também podemos mesclar objetos em um usando a propagação:
const myParents = {
fathersName: 'Michael',
mothersName: 'Louise'
};
const mySiblings = {
brothersName: 'Philip',
sistersName: 'Lara'
};
const myFamily = { ...myParents, ...mySiblings };
console.log(myFamily);
/* output:
{
fathersName: 'Michael',
mothersName: 'Louise',
brothersName: 'Philip',
sistersName: 'Lara'
}
*/
Porém, é importante lembrar que o spread não clona propriedades idênticas ! Abaixo temos dois objetos com brothersName
:
const myParents = {
fathersName: 'Michael',
mothersName: 'Louise',
brothersName: 'Gabriel'
};
const mySiblings = {
brothersName: 'Philip',
sistersName: 'Lara'
};
const myFamily = { ...myParents, ...mySiblings };
console.log(myFamily);
/* output:
{
fathersName: 'Michael',
mothersName: 'Louise',
brothersName: 'Philip',
sistersName: 'Lara'
}
*/
Observe que o objeto final não herda ambas brothersName
as chaves. Na verdade, prevalece apenas um, que é o do segundo objeto .
Copiando matrizes e objetos
Tem a ideia até agora? Se pudermos mesclar arrays e também objetos, isso significa que também podemos copiá-los individualmente:
// creating a shallow copy of coffee:
const coffee = ['coffee', 'water'];
const coffeeCopy = [...coffee];
console.log(coffeeCopy)
// output:
// ['coffee', 'water'];
// creating a shallow copy of mySiblings:
const mySiblings = {
brothersName: 'Philip',
sistersName: 'Lara'
};
const myFamily = {
fathersName: 'Michael',
mothersName: 'Louise',
...mySiblings
};
// Now we can treat brothersName and sistersName as
// a property of myFamily:
console.log(myFamily.brothersName)
// output: Philip
Transformando Strings em Arrays
Também é possível usar o spread para transformar uma string em um array. Isso nos permite ter mais flexibilidade na manipulação de strings, já que poderemos aplicar métodos de array a strings:
const str = 'coffee';
const letters = [...str, 's.', '☕️'];
console.log(letters);// ["c", "o", "f", "f", "e", "e", "s.", "☕️"]
Operador de descanso
Conforme mencionado acima, o operador rest é usado para empacotar elementos em um array. Você verá que o operador rest é um grande aliado ao lidar com muitos valores ou com um número incerto de valores.
Parâmetros de Função
O operador rest nos permite representar um número indefinido de argumentos como um array.
const order = function(beverage, ...otherIngredients) {
console.log(beverage);
console.log(otherIngredients);
};
order('green tea', 'milk', 'brown sugar');
// output:
// green tea
// ['milk', 'brown sugar']
Observe que isso nos permite chamar a mesma função com mais argumentos, já que o operador rest colocará todos eles no otherIngredients
array:
const order = function(beverage, ...otherIngredients) {
console.log(beverage);
console.log(otherIngredients);
};
order('green tea', 'milk', 'brown sugar', 'mint', 'tonka');
// output:
// green tea
// ['milk', 'brown sugar', 'mint', 'tonka']
🍵 Um detalhe importante é que o restante deve ser o último parâmetro da função! Se escrevêssemos function(...otherIngredients, beverage)
o computador não saberia quando parar e esse código geraria um erro.
Desestruturando com descanso e propagação
Rest e spread também são amplamente utilizados na desestruturação. Se você ainda não sabe o que é isso, sugiro meus outros dois artigos aqui: desestruturação de array e desestruturação de objeto.
Usando descanso:
const [a, b, ...others] = [1, 2, 3, 4, 5];
console.log(a, b, others);
// output: 1 2 [3, 4, 5]
Agora, pega essa dica para não confundir rest com spread aqui: o rest fica do lado esquerdo do =
e o spread fica do lado direito do =
.