The same three dots can also do the opposite of spread: pack several things into an array. When ... appears in a function's parameter list, it's called a rest parameter, and it collects "the rest" of the arguments:
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2));
console.log(sum(1, 2, 3, 4, 5));
console.log(sum());
It prints
3 15 0
numbers is a real array containing however many arguments were passed. Now sum works with any number of arguments!
You can have normal parameters first, and the rest parameter last:
function introduceTeam(leader, ...members) {
console.log(`Leader: ${leader}`);
console.log(`Members: ${members.join(", ")}`);
}
introduceTeam("Mia", "Omar", "Zoe", "Sam");
It prints
Leader: Mia Members: Omar, Zoe, Sam
Rest also works in destructuring, to scoop up whatever's left:
const [winner, ...everyoneElse] = ["Nina", "Hugo", "Emma", "Noah"];
console.log(winner);
console.log(everyoneElse);
const user = { id: 7, name: "Gabriel", password: "s3cret!", email: "kb@example.com" };
const { password, ...safeUser } = user;
console.log(safeUser);
It prints
Nina
[ 'Hugo', 'Emma', 'Noah' ]
{ id: 7, name: 'Gabriel', email: 'kb@example.com' }That second example is a really useful trick: it makes a copy of the user object without the password, which is exactly what you'd want before sending user data somewhere it could be seen.
They look identical (...), so how do you tell them apart? Look at where they are:
- On the right side of
=, or in a function call,...unpacks things. That's spread. - On the left side of
=, or in a function definition,...packs things. That's rest.