Unlock JS: Powerful REST and SPREAD Magic You Need to Know

In JavaScript, the rest operator (also called the spread operator) allows us to represent an indefinite number of elements as an array. It’s a helpful tool that can make our code more concise and easier to read. Rest and Spread is quintessential for JS.
Here’s an example of how the rest operator works:

function addNumbers(...numbers) {
  let sum = 0;
  for (const number of numbers) {
    sum += number;
  }
  return sum;
}

console.log(addNumbers(1, 2, 3, 4, 5)); // 15

In this example, the function addNumbers takes an indefinite number of arguments, represented by the three dots (...) followed by the name numbers. This is the rest operator, and it allows us to pass as many arguments as we want to the function. Inside the function, we loop through the numbers array and add up all of the elements. When we call the function, we pass in five arguments: 1, 2, 3, 4, and 5. These arguments are collected into the numbers array, and the function calculates their sum and prints it to the console.

function withNoArgument() {
  console.log("no isses");
}
withNoArgument("Asif", "Dev");

Before diving into rest and spread even more; let’s have some background info.
What do you think the output for the above code?
Yes, you guessed it right. JavaScript will not throw any error when we call a parameter-less function with any number of parameter and it will output ‘no issues‘.

As such; the following code is also valid:

function sum(a, b) {
  return a + b;
}

alert( sum(1, 2, 3, 4, 5) );

There will be no error because of all the extra arguments but in the result only the first two will be counted.

Rest Operator

The rest of the parameters can be included in the function definition by using three dotsfollowed by the name of the array that will contain them. The dots literally mean “gather the remaining parameters into an array”. For example:

function restExample (a, b, ...restOfThem) {
  console.log(restOfThem.length);
}
restExample(25, 23, 2, 11, 8, 17, 6);

This code assigns 25 to a, 23 to b and [2, 11, 8, 17, 6] to the variable restOfThem.

The …rest must always be last. The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:

function f(arg1, ...rest, arg2) { // arg2 after ...rest
  // error
}

There is also a special array-like object named arguments that contains all arguments by their index. Let’s get back to the first example –

function withNoArgument() {
  console.log(arguments[0]);
 // asif
  console.log(arguments[1]);
 // dev
}
withNoArgument("Asif", "Dev");

When rest parameters did not exist in the language, using arguments was the only way to get all arguments of the function. But the downside is that although arguments is both array-like and iterable, it’s not an array. It does not support array methods, so we can’t call arguments.map(…) for example. Also, it always contains all arguments. We can’t capture them partially, like we did with rest parameters.

So, in short, the rest operator lets us represent an indefinite number of elements as an array, which can be helpful when we don’t know how many elements we’ll need to work with.

The rest operator can also be used in function calls, as shown in the following example:

function logArguments(arg1, arg2, ...otherArgs) {
  console.log(arg1); // "a"
  console.log(arg2); // "b"
  console.log(otherArgs); // ["c", "d", "e"]
}

const args = ["a", "b", "c", "d", "e"];
logArguments(...args);

In this example, the function logArguments takes three arguments: arg1, arg2, and otherArgs. The rest operator is used to represent the remaining arguments as an array. When we call the function with the spread operator (...args), it expands the args array into individual elements, which are then passed as arguments to the function.

Spread Operator

Rest parameters is a way to get an array from the list of parameters. But sometimes we need to do exactly the reverse. For instance, there’s a built-in function Math.max that returns the greatest number from a list. Now let’s say we have an array [3, 5, 1]. How do we call Math.max with it? Passing it “as is” won’t work, because Math.max expects a list of numeric arguments, not a single array. And we can’t manually list items in the code, because we may be unsure how many there are. As our script executes, there could be a lot, or there could be none.

Spread syntax to the rescue! It looks similar to rest parameters, also using , but does quite the opposite. When …arr is used in the function call, it “expands” an iterable object arr into the list of arguments. Like –

let arr1 = [1, -2, 3, 4];
let arr2 = [8, 3, -8, 1];

alert( Math.max(...arr1, ...arr2) ); // 8

We can even combine the spread syntax with normal values. Also, the spread syntax can be used to merge arrays.

We can use spread operator to easily copy array or object to another array or object.

let arr = [1, 2, 3];
let arrCopy = [...arr]; // spread the array into a list of parameters
                        // then put the result into a new array

// do the arrays have the same contents?
alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true

// are the arrays equal?
alert(arr === arrCopy); // false (not same reference)

// modifying our initial array does not modify the copy:
arr.push(4);
alert(arr); // 1, 2, 3, 4
alert(arrCopy); // 1, 2, 3

But why can’t we just write let arrCopy = arr? The answer is, Javascript arrays and objects are passed by reference, not by value. This means that when we write let arrCopy = arr, our new variable arrCopy isn’t actually a copy of arr — it’s a reference that points to arr. So, if we change arr, then arrCopy changes as well.

Suppose we want a new array with all the contents of arr, except now with a new element at the end. We can just use array.push(), assign to the new variable and be done with it; right? Wrong! Because array.push() will just alter both array; which defeats the purpose. So what to do? Yes; spread to the rescue!

let arr = [1, 2, 3];
let newArray = [...arr, 4];

In short, the spread operator allows us to expand an array into individual elements, which can be helpful when we want to combine multiple arrays or when we want to pass the elements of an array as arguments to a function.

Conclusion

Rest and spread are important inclusion in modern JavaScript. The rest operator (…) allows us to call a function with any number of arguments and then access those excess arguments as an array. The rest operator also allows us in destructuring array or objects. The spread operator (…) allows us to expand an iterable like array into its individual elements. ... could be used to represent either a spread operator or a rest parameter. How do we tell the difference? Well it entirely depends on how we use it. Given the context in which we use the three dots, it is easy to tell whether we are using it as a rest parameter or a spread operator. There’s an easy way to distinguish between them:

  • When … is at the end of function parameters, it’s “rest parameters” and gathers the rest of the list of arguments into an array.
  • When … occurs in a function call or alike, it’s called a “spread syntax” and expands an array into a list.


Use patterns:

  • Rest parameters are used to create functions that accept any number of arguments.
  • The spread syntax is used to pass an array to functions that normally require a list of many arguments.

Together they help to travel between a list and an array of parameters with ease.

To learn more about the topic; please visit the official mozilla link: rest and spread

Leave a Comment