What are spread and rest operators in JavaScript?

Beginner7 min interview
Skills tested:
Spread syntax for arrays and objectsRest parameter syntax in function signaturesShallow copy behavior of spreadDestructuring combined with restPractical usage in function argument forwarding

Advertisement

🧩 Scenario

In a real codebase, you will encounter spread when merging objects, cloning arrays, passing array elements as function arguments, and composing React props. You will encounter rest when writing utility functions that accept a variable number of arguments and when destructuring arrays or objects to extract a subset of values. Both operators share the same syntax but appear in opposite contexts: spread expands and rest collects.

Architecture Walkthrough

Spread: Expanding Iterables and Objects

The spread operator (...) expands an iterable (array, string, Set, Map) or an object into its individual elements or properties. In an array context, [...arr] creates a new array by inserting each element of arr. In an object context, { ...obj } creates a new object by copying each enumerable own property of obj.

Spread is shallow. If an array or object contains nested reference types, the spread copy and the original share those nested references. This means spread is appropriate for flat data and for creating new top-level structures, but it does not replace a deep clone for nested data.

Rest: Collecting into an Array

The rest operator looks identical to spread (...) but appears in a different position: in a function parameter list or in a destructuring pattern on the left side of an assignment. In a function parameter list, rest collects all remaining arguments into a real array. In destructuring, rest collects the remaining elements or properties that were not explicitly extracted.

Rest parameters are strictly superior to the legacy arguments object. arguments is array-like but not a real array, so you cannot call .map or .filter on it directly. arguments is also not available in arrow functions. Rest parameters are a proper array from the start and work in all function types.

Practical Patterns

Spreading one object into another is the standard way to merge or override properties. The last spread wins when there are duplicate keys, making the order significant. This pattern appears constantly in React for passing props with overrides, in Redux for producing new state objects, and in any function that applies default options.

Combining destructuring with rest extracts specific elements and collects the remainder: const [first, ...rest] = arr. This is more expressive than slicing and communicates intent clearly. The same pattern works with objects: const { id, ...remaining } = user extracts id and collects everything else.


Key Code Explained

// Spread: merging and cloning arrays
const a = [1, 2, 3];
const b = [4, 5, 6];
const merged = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
const copy = [...a];         // shallow copy

// Spread: merging objects (last key wins on collision)
const defaults = { theme: 'light', lang: 'en' };
const userPrefs = { lang: 'ar' };
const config = { ...defaults, ...userPrefs };
// { theme: 'light', lang: 'ar' }

// Spread: expanding array into function arguments
const nums = [3, 1, 4, 1, 5];
const max = Math.max(...nums); // equivalent to Math.max(3, 1, 4, 1, 5)

// Rest: variadic function
function sum(...values) {
  return values.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10

// Rest in destructuring
const [head, ...tail] = [10, 20, 30, 40];
// head = 10, tail = [20, 30, 40]

const { id, ...profile } = { id: 1, name: 'Ghazi', role: 'admin' };
// id = 1, profile = { name: 'Ghazi', role: 'admin' }

The object destructuring with rest ({ id, ...profile }) is especially useful when you need to pass all properties of an object to a child component except one, which is a common React pattern.


Tradeoffs

ApproachProCon
Spread for cloningConcise, readable, sufficient for flat dataShallow only, nested references are shared
Rest parametersReal array, works in arrow functions, expressiveMust be last in parameter list, cannot have named params after it
arguments objectAvailable in all legacy code without any syntax changeNot a real array, not available in arrow functions, harder to work with

What Interviewers Actually Check

  • Whether you can clearly distinguish spread (expands) from rest (collects) despite the same ... syntax
  • Whether you know spread produces a shallow copy, not a deep clone
  • Whether you know rest parameters produce a real array while arguments does not
  • Whether you understand that last spread wins on duplicate object keys
  • Whether you can use destructuring with rest to split an array or omit a property from an object

Follow-Up Questions

  1. What happens if you try to spread a non-iterable value, such as a number or a plain object, in an array context?
  2. How would you write a function that accepts a required first argument and any number of additional arguments after it?
  3. If you spread two objects and both have a nested object under the same key, what does the result look like?
  4. When spreading props in React, what are the performance and readability tradeoffs compared to passing each prop explicitly?
  5. A teammate proposes using spread everywhere to "clone" state in a Redux reducer. What would you verify before approving?

Common Candidate Mistakes

  • Confusing rest parameters with the arguments object and not knowing they differ in arrow functions
  • Using spread to deep-clone a nested object and being surprised that nested references are still shared
  • Placing a rest parameter in a non-final position in a function signature, which causes a SyntaxError
  • Using spread on a non-iterable value in an array context and not understanding why it throws
  • Not realizing that when spreading objects with duplicate keys, the later spread overwrites the earlier one

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you explain the difference between spread and rest using the same ... syntax?
  • Can you demonstrate merging two arrays and two objects using spread?
  • Can you write a variadic function using rest parameters and explain why it is preferred over arguments?
  • Can you explain that spread produces a shallow copy, not a deep clone?
  • Can you show how rest and destructuring work together to extract the first element and collect the rest?

Summary

Spread and rest use the same ... syntax but serve opposite purposes. Spread appears on the right side of an assignment or inside a function call, expanding an array or object into its individual parts. Rest appears on the left side in destructuring or in a function parameter list, collecting multiple individual values into a single array.

Spread is the standard way to merge arrays, compose objects, and pass array elements as function arguments. Its key limitation is that it produces a shallow copy, so nested objects remain shared references. Rest parameters are the modern replacement for the arguments object, offering a real array with all standard array methods and full compatibility with arrow functions.

Knowing when to use each and understanding the shallow copy limitation of spread are the two signals interviewers look for on this question.

Related Videos
Watch these videos to learn more about this topic
Frequently Asked Questions

Can spread and rest be used together?

Yes, rest collects parameters while spread expands them — perfect for flexible function arguments.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement