Loading...
Loading...
Collect any number of arguments into a real array with ...rest.
Module 9 · Modern JavaScript (ES6+)
ES2015 and later additions transformed how JavaScript is written. let and const, template literals, modules, spread/rest, optional chaining, and nullish coalescing are now standard in every modern codebase.
Learn Rest Parameters in JavaScript — covering Basics, vs arguments, With Other Params, In Destructuring with interactive visual examples and step-by-step explanations.
ES2015 (ES6) and the releases that followed added the syntax modern JavaScript is written in today. let and const replaced var, template literals replaced string concatenation, and import/export replaced global script tags.
This module covers the ES6+ features you will see in every codebase and job interview. Each chapter shows the old pattern alongside the modern equivalent so you can read legacy code and write idiomatic JavaScript.
Understanding rest parameters is essential for every JavaScript developer. It shows up in frontend UI code, backend APIs, and framework internals — and getting it wrong leads to bugs that are hard to trace. This chapter builds intuition with visuals so the behavior sticks.
...rest collects remaining arguments into an array.
// Collect all arguments: function sum(...numbers) { return numbers.reduce((total, n) => total + n, 0); } sum(1, 2, 3); // 6 sum(1, 2, 3, 4, 5); // 15 sum(); // 0 // 'numbers' is a real Array: function show(...args) { console.log(Array.isArray(args)); // true console.log(args.length); args.forEach(a => console.log(a)); args.map(a => a * 2); // all array methods work! } // Accepts any number of arguments: function log(...messages) { messages.forEach(msg => console.log(msg)); } log("hello"); log("a", "b", "c", "d");
Rest parameters replace the old arguments object.
// Old way — arguments object: function old() { console.log(arguments[0]); // works arguments.forEach(x => x); // ❌ TypeError! // arguments is array-LIKE, not a real array // Had to convert: var args = Array.prototype.slice.call(arguments); args.forEach(x => console.log(x)); // now works } // New way — rest parameters: function modern(...args) { console.log(args[0]); // works args.forEach(x => console.log(x)); // works! args.map(x => x * 2); // works! // It's already a real array }
Rest parameters give you a real Array with all methods. The old arguments object was array-like but not an actual Array.
Combine named parameters with rest — rest must be last.
// Named params + rest (rest must be LAST): function tag(name, ...classes) { return `<${name} class="${classes.join(" ")}">`; } tag("div", "container", "flex", "p-4"); // '<div class="container flex p-4">' // First arg is special, rest collected: function printf(template, ...values) { return template.replace(/%s/g, () => values.shift()); } printf("Hello %s, you have %s items", "Alice", 3); // "Hello Alice, you have 3 items" // ❌ Rest must be the last parameter: function bad(...rest, last) {} // SyntaxError! function bad(...a, ...b) {} // SyntaxError! (only one rest) // ✓ These work: function ok(a, b, ...rest) {} function ok(...all) {}
Rest works in array and object destructuring too.
// Array destructuring — collect remaining: const [first, second, ...rest] = [1, 2, 3, 4, 5]; // first = 1, second = 2, rest = [3, 4, 5] const [head, ...tail] = "hello".split(""); // head = "h", tail = ["e", "l", "l", "o"] // Object destructuring — collect remaining properties: const { name, age, ...details } = { name: "Alice", age: 25, city: "Tokyo", role: "dev" }; // name = "Alice", age = 25 // details = { city: "Tokyo", role: "dev" } // Remove properties immutably: const { password, ...safeUser } = user; // safeUser has everything except password // Nested: const { data: { id, ...metadata }, ...response } = apiResult; // In function parameters: function UserCard({ name, avatar, ...rest }) { // rest = all other props return <div {...rest}>{name}</div>; }
Common real-world uses of rest parameters.
// 1. Wrapper/decorator functions: function withLogging(fn) { return function(...args) { console.log(`Calling ${fn.name} with`, args); const result = fn(...args); // spread back out! console.log(`Result:`, result); return result; }; } const loggedAdd = withLogging((a, b) => a + b); loggedAdd(2, 3); // logs args, returns 5 // 2. Pipe/compose: const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x); const process = pipe( x => x * 2, x => x + 1, x => `Result: ${x}` ); process(5); // "Result: 11" // 3. Event emitter: class EventBus { #handlers = {}; on(event, fn) { (this.#handlers[event] ??= []).push(fn); } emit(event, ...args) { this.#handlers[event]?.forEach(fn => fn(...args)); } } // 4. Partial application: function partial(fn, ...presetArgs) { return (...laterArgs) => fn(...presetArgs, ...laterArgs); } const add10 = partial((a, b) => a + b, 10); add10(5); // 15
Common questions about rest parameters.