Operadores Spread vs Rest em JavaScript
Barbara Robles 🇧🇷
Posted on March 12, 2024
Conteúdo:
Vem aprender a usar os três pontinhos no seu código. Depois desse artigo você não vai mais esquecer a diferença entre eles! 🐱🐱🐱
Definição :
O spread é o operador quer nos permite expandir iteráveis em elementos individuais.
O rest é o operador que usamos para representar um número indefinido de argumentos em um array.
Ambos são escritos utilizando os três pontos ...
, mas você verá que é fácil identificar quando é um spread e quando é um rest! No final tem também uma dica boa para você!
Operador Spread
Concatenando Arrays
O spread permite que unamos dois ou mais arrays, mantendo uma linguagem concisa e limpa.
Vamos tomar um café? ☕️ Considere os dois arrays abaixo:
const coffee = ['café', 'água'];
const spices = ['canela', 'noz-moscada', 'cardamomo'];
Para temperar o café, precisamos misturar os arrays coffee
e spices
. Podemos usar o spread para juntá-los em um único array:
const coffeeReady = [...coffee, ...spices];
console.log(coffeeReady)
// output:
// ['café', 'água', 'canela', 'noz-moscada', 'cardamomo'];
Simples, não? Muito melhor do que escrever item por item de cada um dos dois arrays para formar coffeeReady
.
Importante:
1. Alterações em coffee
não afetarão coffeeReady
!
Para entender melhor: quando fazemos uma cópia, podemos criar uma nova referência ao valor original ou apenas copiar o valor. Criar uma nova referência nada mais é do que criar uma variável que apontará para o local na memória em que está o valor original.
Caso tivéssemos criado uma nova referência, qualquer alteração em coffee
alteraria coffeeReady
e vice-e-versa, pois ambos apontariam para o dado armazenado no mesmo local. 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.
No entanto, alguns detalhes poderiam mudar esse quadro! Isso porque...
2. O spread apenas cria uma cópia superficial (shallow copy)!
Isso significa que, dependendo dos dados contidos em coffee
, algumas alterações poderiam sim alterar coffeeReady
! Se coffee
contivesse algum valor não-primitivo, o computador teria criado uma referência para os valores na memória. Assim, qualquer alteração em um array, afetaria o outro, em relação aos dados não-primitivos, já que ambos estariam armazenando uma referência para o mesmo local da memória. Veja abaixo:
let a = [1, [2, 3]];
const b = [4, 5, 6];
// [2, 3] é um array aninhado em a, e portanto
// é um valor não-primitivo
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 alterar a[0]
não afetou c
, pois alteramos um valor primitivo, ou seja a[0]
e c
apontam para valores iguais, mas que estão em locais diferentes na memória. No entanto, alterar a[1][0]
, modificou c
, porque alteramos um array, que é um valor não-primtivo. Assim, alteramos um valor contido no espaço de memória, para o qual tanto a[1][0]
quanto c
apontam.
Unindo Objetos
Também podemos unir objetos em um só usando o spread:
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'
}
*/
No entanto, é 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'
}
Veja que o objeto final não herda as duas chaves brothersName
. Na verdade, apenas uma prevalece, que é a do segundo objeto.
Copiando Arrays e Objetos
Pegou a ideia até agora? Se podemos unir arrays e também objetos, isso significa também que podemos copiá-los individualmente:
// criando uma cópia superficial de coffee:
const coffee = ['café', 'água'];
const coffeeCopy = [...coffee];
console.log(coffeeCopy)
// output:
// ['café', 'água'];
// criando uma cópia superficial de mySiblings:
const mySiblings = {
brothersName: 'Philip',
sistersName: 'Lara'
};
const myFamily = {
fathersName: 'Michael',
mothersName: 'Louise',
...mySiblings
};
// e agora podemos tratar brothersName e sistersName como
// uma propriedade de 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 ao manipular strings, pois dessa maneira conseguimos aplicar métodos de arrays em strings:
const str = 'coffee';
const letters = [...str, 's.', '☕️'];
console.log(letters);// ["c", "o", "f", "f", "e", "e", "s.", ☕️"]
Operador Rest
Conforme dito acima, o operador rest é usado para empacotar elementos em um array. Você verá que o rest é um grande aliado para quando lidamos com muitos valores ou número de valores incertos.
Parâmetros de Função
O operador rest permite representar um número indefinido de argumentos como um array.
const order = function(beverage, ...otherIngredients) {
console.log(beverage);
console.log(otherIngredients);
};
order('chá verde', 'leite', 'açúcar mascavo');
// output:
// chá verde
// ['leite', 'açúcar mascavo']
Veja que isso nos permite chamar a mesma função com mais argumentos, pois o rest os colocará todos no array otherIngredients
:
const order = function(beverage, ...otherIngredients) {
console.log(beverage);
console.log(otherIngredients);
};
order('chá verde', 'leite', 'açúcar mascavo', 'hortelã', 'cumaru');
// output:
// chá verde
// ['leite', 'açúcar mascavo', 'hortelã', 'cumaru']
🍵 Um detalhe importante é que o rest deve ser o último parâmetro na função! Se escrevêssemos function(...otherIngredients, beverage)
o computador não saberia quando parar e isso geraria um erro.
Desestruturação com Rest e Spread
O rest e o spread também são muito utilizados em desestruturação. Se você não sabe ainda o que é isso, sugiro meus outros dois artigos aqui: desestruturação de arrays e desestruturação de objetos.
Usando rest:
const [a, b, ...others] = [1, 2, 3, 4, 5];
console.log(a, b, others);
// output: 1 2 [3, 4, 5]
Usando spread:
const array = [1, 2, ...[3, 4, 5]];
console.log(array);
// output: [1, 2, 3, 4, 5]
Agora, pega essa dica para você não confundir rest com o spread aqui: o rest fica do lado esquerdo de =
e o spread fica do lado direito de =
.
...rest = ☕️
🍵 = ...spread
Obrigada por chegar até aqui! Espero que esse post tenha te ajudado! Comenta o que achou!
Posted on March 12, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.