fbpx

Rest Parameter and Spread syntax and their use-case

Rest syntax looks exactly like spread syntax. In a way, rest syntax is the opposite of spread syntax. Spread syntax “expands” an array into its elements, while rest syntax collects multiple elements and “condenses” them into a single element.

Rest Parameter:

The rest parameter syntax allows us to represent an indefinite number of arguments as an array.

Syntax

function f(a, b, ...theArgs) {
  // ...
}

We can call a function with less or more number of parameter than function can accept. It will not give any error. But we can use with in function only number of parameter accept by function.

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

console.log(sum(1, 2));
// expected output: 3

console.log(sum(1, 2, 3, 4));
// expected output: 3

A function’s last parameter can be prefixed with ... which help to accept all extra parameter in the form of array, which we can use with in function.

function myFun(a,  b, ...manyMoreArgs) {
  console.log("a", a)
  console.log("b", b)
  console.log("manyMoreArgs", manyMoreArgs)
}

myFun("one", "two", "three", "four", "five", "six")

// Console Output:
// a, one
// b, two
// manyMoreArgs, [three, four, five, six]

In above example, the first argument is mapped to a and the second to b, so these named arguments are used as normal.

However, the third argument, manyMoreArgs, will be an array that contains the 3rd, 4th, 5th, 6th … nth — as many arguments that the user includes.

The rest parameters must be at the end

function f(a, ...theArgs, b) {
  // error
}
f(1,2,3,4) // Uncaught SyntaxError: Rest parameter must be last formal parameter

What is earlier rest parameter ?

Earlier then rest parameter, there is the way of handling is “arguments”. But there is a difference between rest and arguments.

function sortArguments() {
  return arguments 
}
console.log(sortArguments(5, 3, 7, 1)) // Arguments(4) [5, 3, 7, 1, callee: ƒ, Symbol(Symbol.iterator): ƒ]

Let see one more example where we are passing parameter also and we see that parameter got there value also but “arguments” also receive all passed argument.

function sortArguments(a,b) {
  console.log(a,b) // 5,3
  return arguments 
}
console.log(sortArguments(5, 3, 7, 1)) // Arguments(4) [5, 3, 7, 1, callee: ƒ, Symbol(Symbol.iterator): ƒ]

To use Array methods on the arguments object, it must be converted to a real array first. Since arguments is not array.

function sortArguments() {
  let args = Array.from(arguments)
  let sortedArgs = args.sort()
  return sortedArgs
}
console.log(sortArguments(5, 3, 7, 1))  // 1, 3, 5, 7

Difference between rest parameters and the arguments object

There are three main differences between rest parameters and the arguments object:

  • rest parameters are only the ones that haven’t been given a separate name (i.e. formally defined in function expression), while the arguments object contains all arguments passed to the function;
  • the arguments object is not a real array, while rest parameters are Array instances, meaning methods like sortmapforEach or pop can be applied to it directly;
  • the arguments object has additional functionality specific to itself (like the callee property).

Spread Syntax:

Spread syntax (…) allows you to expand any iterable like an array or string in place.

Spread syntax (...) allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

MDN
function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers));
// expected output: 6

Syntax:

For function calls:

myFunction(...iterableObj);

For array literals or strings:

[...iterableObj, '4', 'five', 6];

For object literals (new in ECMAScript 2018):

let objClone = { ...obj };

Spread in array literals:

The spread syntax very helpful while using with array. Many times we can replace push(), concat() array method.

let str = "Hello";
console.log( [...str] ); // [H,e,l,l,o]

Merging two array:

const parts = ['shoulders', 'knees']; 
const lyrics = ['head', ...parts, 'and', 'toes']; 
//  ["head", "shoulders", "knees", "and", "toes"]
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];

arr1 = [...arr2, 7,8,9, ...arr1];
//  arr1 is now [3, 4, 5, 7,8,9,0, 1, 2]

Copy an array:

const arr = [1, 2, 3];
const arr2 = [...arr]; // like arr.slice()

arr2.push(4);
//  arr2 becomes [1, 2, 3, 4]
//  arr remains unaffected

Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays

Point to Remember

Spread in object literals:

const obj1 = { foo: 'bar', x: 42 };
const clonedObj = { ...obj1 }; // // Object { foo: "bar", x: 42 }
const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };

const mergedObj = { ...obj1, ...obj2 }; // // Object { foo: "baz", x: 42, y: 13 }

Spread syntax (other than in the case of spread properties) can be applied only to iterable objects:

const obj = {'key1': 'value1'};
const array = [...obj]; // TypeError: obj is not iterable

Spread in function calls:

function myFunction(x, y, z) { }
const args = [0, 1, 2];
myFunction(...args);

It is common to use Function.prototype.apply() in cases where you want to use the elements of an array as arguments to a function. But now you can use spread syntax.

function myFunction(x, y, z) { }
const args = [0, 1, 2];
myFunction.apply(null, args);

When calling a constructor with new it’s not possible to directly use an array and apply(). However, an array can be easily used with spread syntax:

const dateFields = [1970, 0, 1];  // 1 Jan 1970
const d = new Date(...dateFields);

Rest syntax looks exactly like spread syntax. In a way, rest syntax is the opposite of spread syntax. Spread syntax “expands” an array into its elements, while rest syntax collects multiple elements and “condenses” them into a single element

References: