Uwaga! Trwają prace nad nową wersją serwisu. Mogą występować przejściowe problemy z jego funkcjonowaniem. Przepraszam za niedogodności!
⛔ Masz dość walki z kodem i samym sobą? 🔄 Czas na RESET! ✅ Dołącz do bezpłatnego wyzwania!
Wyglądają tak samo – to trzy kropki – a jednak są wykorzystywane do innych celów. Teoretycznie nie trzeba znać ich nazw, by umieć je stosować, lecz warto usystematyzować swoją wiedzę zanim o rozproszenie lub parametr reszty zapyta Cię rekruter techniczny!
Rozproszenie i parametr reszty wyglądają tak samo: to trzy kropki. W pewnym uproszczeniu mają jednak „przeciwne” role, które często u osób początkujących powodują problem z nazewnictwem. Czym jest jedno, a czym drugie? Warto umieć je nie tylko stosować, ale również odróżnić – choćby po to, by nie zaliczyć wpadki na rozmowie rekrutacyjnej (np. podczas omawiania kodu w trakcie pair programmingu).
„Rozprasza” elementy tam, gdzie dostajemy je „w pakiecie” – czyli w postaci stringa, tablicy czy obiektu. Spread często używany jest np. przy tworzeniu jednej tablicy z dwóch lub łączeniu obiektów.
Przydaje się np. w pracy z Reactem przy przekazywaniu wartości między komponentami przez tzw. props. Załóżmy, że otrzymaliśmy dwa obiekty z ustawieniami dla stylów i chcemy je połączyć w jeden obiekt styles. Zrobimy to w ten sposób:
const spaceStyles = {
margin: "60px",
padding: "10px"
};
const sizeStyles = {
width: "100px",
height: "150px"
};
styles = { ...spaceStyles, ...sizeStyles };
Teraz obiekt styles wygląda tak (kolejność kluczy nie ma znaczenia, może się zmienić):
{
margin: "60px",
padding: "10px",
width: "100px",
height: "150px"
}

Uwaga: rozproszenie pozwala nam tworzyć nowe obiekty, ale nie pozwala mutować tych, które już mamy – oczywiście jeśli zgodnie z dobrymi praktykami stosujemy const (sprawdź przykład poniżej). Do tego nadal trzeba wykorzystywać metodę Object.assign():
const styles = {
margin: "60px",
padding: "10px",
width: "100px",
height: "150px"
}
const colorStyles = {
color: "red",
backgroundColor: "yellow"
}
Object.assign( styles, colorStyles );
Widzisz? W takiej sytuacji nie tworzymy nowego obiektu, lecz dodajemy nowe wartości do już istniejącego (mutujemy go). Nasz obiekt styles wygląda teraz tak:
{
margin: "60px",
padding: "10px",
width: "100px",
height: "150px",
color: "red",
backgroundColor: "yellow"
}
W przykładzie mamy dwa „pakiety owoców”: tablicę yellowFruit i greenFruit.
const yellowFruit = ["melon", "banana", "lemon"]; const greenFruit = ["apple", "grapes"];
Chcemy połączyć je w ogólny zbiór owoców, np. tablicę fruit. Dzięki rozproszeniu robimy to w jednej linii i zachowujemy bardzo dobrą czytelność kodu:
const fruit = [ ...yellowFruit, ...greenFruit ];
Co otrzymujemy? Tylko jedną tablicę, ponieważ wartości zgromadzone w tablicach yellowFruit i greenFruit zostały rozproszone – „pozbyliśmy się ich opakowania” w postaci tablic:
["melon", "banana", "lemon", "apple", "grapes"]
Uwaga: tutaj do mutowania tablicy (gdy nie chcemy tworzyć nowej) zastosujemy odpowiednie metody, np. .push() czy .unshift() w połączeniu z rozproszeniem:
const fruit = ["apple", "pear"]; const yellowFruit = ["melon", "banana", "lemon"]; fruit.push(...yellowFruit);
W tej sytuacji nie tworzymy nowej tablicy, lecz rozszerzamy pierwszą o nowe elementy. Tablica fruit wygląda teraz tak:
["apple", "pear", "melon", "banana", "lemon"];
Podobnie jak w przypadku destrukturyzacji, rozproszenie można zastosować także do stringu:
const word = "mouse"; const letters = [ "a", "p", ...word, "d"];
W ten sposób dodaliśmy litery do nowo utworzonej tablicy:
["a", "p", "m", "o", "u", "s", "e", "d"]
Niejednokrotnie spotkasz się z tym, że rozproszenie używane jest do tworzenia kopii tablic i obiektów, np. tak:
// kopiowanie obiektu
const style = {
margin: "60px",
padding: "10px"
}
const newStyle = { ...style }
// kopiowanie tablicy
const numbers = [ 1, 2, 3, 4, 5 ]
const newNumbers = [ ...numbers ]
Trzeba jednak pamiętać, że w przypadku obiektów dochodzi w ten sposób do utworzenia kopii płytkiej (shallow copy) – tak samo jak wtedy, gdy stosujemy metodę Object.assign(). Jeśli chcesz zgłębić ten temat, zapraszam Cię do mojego wideo, w którym omawiam płytkie i głębokie kopiowanie obiektu.
O wykorzystaniu rozproszenia podczas destrukturyzacji przeczytasz w moim artykule Czym jest destrukturyzacja w JavaScript i jak ją stosować.
Słowo klucz, które pozwoli Ci rozróżnić rest od spread, to „parametr”. Gdzie mamy parametry? Tylko podczas tworzenia funkcji (czy to w formie deklaracji funkcji czy wyrażenia funkcyjnego). Zaznaczam: tylko podczas tworzenia funkcji. Gdy wywołujemy funkcję, mamy już do czynienia z argumentami (nie parametrami!).
Przykładowo to są parametry a i b oraz c i d:
function sum( a, b ) {
return a + b
}
const subtract = function( c, d ) {
return c - d
}
A to argumenty 2 i 10 oraz 10.5 i 0.5:
sum( 2, 10 ) subtract(10.5, 0.5)
Jeśli nadal ich nie rozróżniasz, zajrzyj do ostatniej sekcji mojego artykułu „Front end – pojęcia, które mylą się na początku nauki (część 1)”.
Ustaliliśmy zatem, że parametr reszty to parametr funkcji. Mówiliśmy już też, że stanowi pewnego rodzaju „przeciwieństwo” rozproszenia. W rozproszeniu mieliśmy „pakiet” wartości, które „rozrzucaliśmy”. Parametr reszty zaś działa na odwrót: zbiera takie „rozrzucone” elementy w „pakiet” – tablicę (tak, tym razem to zawsze tylko tablica).
W poniższym przykładzie mamy funkcję, która wyświetla (dodaje do elementu body) listę zakupów o konkretnej nazwie. Zwróć uwagę, że nasz parametr reszty (...products) jest ostatnim parametrem – to warunek konieczny!
function displayList(name, ...products) {
const ulElement = document.createElement("ul");
ulElement.innerText = name;
products.forEach(function(product) {
const liElement = document.createElement("li");
liElement.innerText = product;
ulElement.appendChild(liElement);
})
document.body.appendChild(ulElement)
}
Dzięki takiemu rozwiązaniu za jednym zamachem możemy stworzyć długa listę produktów, wpisując kolejne argumenty za nazwą listy:
displayList("Grocery", "bananas", "apples", "cheese", "crisps", "pasta")
Uruchom powyższy kod np. w JSFiddle, by sprawdzić, w jaki sposób działa.
Chcesz przetestować kod z grafiki? Możesz skopiować poniższy przykład:
function createPerson( name, ...nicknames) {
let fullName = name;
nicknames.forEach( nick => {
fullName = fullName + ' ' + nick
})
return fullName
}
const person = createPerson("John", "Cat", "The Greatest");
console.log(person)
Rozproszenie (spread) to wyjęcie wartości z „opakowania” (tablicy, obiektu czy stringa), by można było przekazać je gdzieś indziej.
Parametr reszty (rest) to parametr funkcji, pod który podczas wywołania funkcji możemy podstawić dowolną liczbę argumentów.
Udostępnij ten artykuł:
Chcesz zostać (lepszym) programistą i lepiej zarabiać?
🚀 Porozmawiajmy o nauce programowania, poszukiwaniu pracy, o rozwoju kariery lub przyszłości branży IT!
Umów się na ✅ bezpłatną i niezobowiązującą rozmowę ze mną.
Chętnie porozmawiam o Twojej przyszłości i pomogę Ci osiągnąć Twoje cele! 🎯