JavaScript has a built-in ...
operator that makes it easier to work with indefinite numbers of elements. Depending on the context, it's called either a rest operator or spread operator.
When ...
appears on the left-hand side of an assignment, those three dots are known as the rest
operator. The three dots together with a variable name is called a rest element. It collects zero or more values, and stores them into a single array.
const [a, b, ...everythingElse] = [0, 1, 1, 2, 3, 5, 8];
a;
// => 0
b;
// => 1
everythingElse;
// => [1, 2, 3, 5, 8]
Note that in JavaScript, unlike some other languages, a rest
element cannot have a trailing comma. It must be the last element in a destructuring assignment. The example below throws a SyntaxError
:
const [...items, last] = [2, 4, 8, 16]
Similarly to arrays, the rest operator can also be used to collect one or more object properties and store them in a single object.
const { street, ...address } = {
street: 'Platz der Republik 1',
postalCode: '11011',
city: 'Berlin',
};
street;
// => 'Platz der Republik 1'
address;
// => {postalCode: '11011', city: 'Berlin'}
When ...
appears in a function definition next to its last argument, that parameter is called a rest parameter. It allows the function to accept an indefinite number of arguments as an array.
function concat(...strings) {
return strings.join(' ');
}
concat('one');
// => 'one'
concat('one', 'two', 'three');
// => 'one two three'
When ...
appears on the right-hand side of an assignment, it's known as the spread
operator. It expands an array into a list of elements. Unlike the rest element, it can appear anywhere in an array literal expression, and there can be more than one.
const oneToFive = [1, 2, 3, 4, 5];
const oneToTen = [...oneToFive, 6, 7, 8, 9, 10];
oneToTen;
// => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const woow = ['A', ...oneToFive, 'B', 'C', 'D', 'E', ...oneToFive, 42];
woow;
// => ["A", 1, 2, 3, 4, 5, "B", "C", "D", "E", 1, 2, 3, 4, 5, 42]
Similarly to arrays, the spread operator can also be used to copy properties from one object to another.
let address = {
postalCode: '11011',
city: 'Berlin',
};
address = { ...address, country: 'Germany' };
// => {
// postalCode: '11011',
// city: 'Berlin',
// country: 'Germany',
// }
Your friend Linus is a train driver who drives cargo trains between cities. Although they are amazing at handling trains, they are not amazing at handling logistics or computers. They would like to enlist your programming help organizing train details and correcting mistakes in route data.
To practice, use the rest or spread operator to solve each of the tasks below.
Your friend has been keeping track of each wagon identifier (ID), but they are never sure how many wagons the system is going to have to process at any given time.
It would be much easier for the rest of the logistics program to have this data packaged into a unified array
.
Implement a function getListOfWagons
that accepts an arbitrary number of wagon IDs which are the IDs of each wagon.
Each ID will be a positive integer.
The function should then return the given IDs as a single array
.
getListOfWagons(1, 7, 12, 3, 14, 8, 5);
// => [1, 7, 12, 3, 14, 8, 5]
At this point, you are starting to get a feel for the data and how it's used in the logistics program. The ID system always assigns the locomotive an ID of 1, with the remainder of the wagons in the train assigned a randomly chosen ID greater than 1.
Your friend had to connect two new wagons to the train and forgot to update the system!
Now, the first two wagons in the train array
have to be moved to the end, or everything will be out of order.
Linus would be really grateful to you for fixing their mistakes.
Implement a function fixListOfWagons
that accepts an array of the id of each wagon.
It return
s an array
where the 2 first elements repositioned to the end of the array
so that the locomotive can be in the front.
eachWagonsID = [2, 5, 1, 7, 4, 12, 6, 3, 13];
fixListOfWagons(eachWagonsID);
// => [1, 7, 4, 12, 6, 3, 13, 2, 5]
Uh-oh. some wagons seem to have gone missing.
Fortunately, your friend just found another array
which appears to contain the missing wagon IDs, and would like you to add them into the main wagon ID array
.
All they can remember is that the missing values should be placed directly after the designated locomotive.
Given this new information, write a function called correctListOfWagons
that takes two arrays which have the IDs of each wagon as the arguments.
The wagon IDs of the second array
should be added into the first array
directly after the locomotive (ID 1).
eachWagonsID = [1, 5, 20, 7, 4, 8];
missingWagons = [3, 17, 6, 15];
correctListOfWagons(eachWagonsID, missingWagons);
// => [1, 3, 17, 6, 15, 5, 20, 7, 4, 8]
Now that all the wagon data is correct, your friend would like you to update the systems routing information.
Initial routing information has been constructed as an object
, and you friend would like you to update it with the additions provided.
Every route requires slightly different information, so your friend would really prefer a generic solution.
Implement a function extendRouteInformation
that accepts two objects
.
The first object
contains which cities the train route moves between.
The second object
contains other routing details such as train speed or length.
The function should return a consolidated object
with all routing information.
The variable moreRouteInformation
can contain different properties.
route = { from: 'Berlin', to: 'Hamburg' };
moreRouteInformation = { length: '100', speed: '50' };
extendRouteInformation(route, moreRouteInformation);
// => {from: "Berlin", to: "Hamburg", length: "100", speed: "50"}
Your friend has noticed that they don't need the arrival time in the routing information. Therefore your friend would like you to separate the arrival time from the routing information.
Implement a function separateTimeOfArrival
that accepts an object with the routing information.
The function should return an array where the first element of the array is the arrival time and the second element is an object with the routing information without arrival time.
routeInformation = {
from: 'Berlin',
to: 'Hamburg',
length: '100',
timeOfArrival: '10:10',
};
separateTimeOfArrival(routeInformation);
// => ["10:10", {from: "Berlin", to: "Hamburg", length: "100"}]
Sign up to Exercism to learn and master JavaScript with 36 concepts, 153 exercises, and real human mentoring, all for free.