Suggest an editImprove this articleRefine the answer for “Spread and rest operator”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**The three dots `...` are one syntax with two opposite roles: spread unpacks an array or object into separate elements, while rest gathers the remaining elements back into an array or object.** Context decides which role applies: inside an array or object literal and in a function call it is spread, in function parameters and in destructuring it is rest. Both are shallow, so nested structures stay shared by reference. ```javascript const nums = [1, 2, 3]; const copy = [0, ...nums]; // spread: unpacked const [head, ...tail] = copy; // rest: gathered the remainder console.log(copy, head, tail); // [0, 1, 2, 3] 0 [1, 2, 3] ``` **Key point:** spread expands, rest gathers; position decides which, and the copy is always shallow.Shown above the full answer for quick recall.Answer (EN)Image**The `...` operator is one syntax with two roles: spread unpacks an iterable or an object's properties into separate elements, while rest gathers the remaining elements into a single array or object.** The role is decided not by the operator itself but by where it stands: in a literal or a function call it is spread, in function parameters and in destructuring it is rest. ## Theory ### TL;DR - `...` in a literal or a call expands values: `[...arr]`, `{...obj}`, `sum(...nums)`. - `...` in destructuring or in a parameter list gathers the remainder: `[a, ...rest]`, `function fn(...args)`. - Spread makes a shallow copy: nested objects and arrays are copied by reference. - Spread over objects merges properties, and a later key overwrites an earlier one. - It is the modern replacement for `concat`, `Object.assign` and `Array.prototype.slice.call(arguments)`. ### Quick example ```javascript const numbers = [1, 2, 3]; const moreNumbers = [0, ...numbers, 4, 5]; // spread: the array is unpacked console.log(moreNumbers); // [0, 1, 2, 3, 4, 5] const [first, ...rest] = moreNumbers; // rest: the remainder is gathered console.log(first); // 0 console.log(rest); // [1, 2, 3, 4, 5] ``` ### Spread: unpacking arrays Spread is used to unpack (expand) an array or an object into separate elements. ```javascript const numbers = [1, 2, 3]; const moreNumbers = [0, ...numbers, 4, 5]; console.log(moreNumbers); // [0, 1, 2, 3, 4, 5] ``` Here `...numbers` expanded the array `[1, 2, 3]` inside a new array. Copying arrays: ```javascript const arr1 = [1, 2, 3]; const arr2 = [...arr1]; console.log(arr2); // [1, 2, 3] console.log(arr1 === arr2); // false (a new array) ``` This is a shallow copy: only the outer array is new. Merging arrays: ```javascript const a = [1, 2]; const b = [3, 4]; const c = [...a, ...b]; console.log(c); // [1, 2, 3, 4] ``` ### Spread in function calls In a call, spread turns an array into a list of separate arguments. ```javascript function sum(a, b, c) { return a + b + c; } const nums = [1, 2, 3]; console.log(sum(...nums)); // 6 ``` > `...nums` turns `[1, 2, 3]` into `sum(1, 2, 3)`. ### Spread with objects The same syntax copies own enumerable properties from one object into another. ```javascript const user = { name: 'Alex', age: 25 }; const newUser = { ...user, city: 'Paris' }; console.log(newUser); // { name: 'Alex', age: 25, city: 'Paris' } ``` When keys collide, the later value overwrites the earlier one: ```javascript const merged = { a: 1, ...{ a: 2, b: 3 } }; console.log(merged); // { a: 2, b: 3 } ``` ### Rest: gathering the remainder Rest works the other way round: it does not unpack, it gathers the elements that are left into an array or an object. In arrays: ```javascript const [first, ...rest] = [1, 2, 3, 4]; console.log(first); // 1 console.log(rest); // [2, 3, 4] ``` In objects: ```javascript const user = { name: 'Alex', age: 25, city: 'Paris' }; const { name, ...info } = user; console.log(name); // Alex console.log(info); // { age: 25, city: 'Paris' } ``` In functions: ```javascript function sum(...numbers) { return numbers.reduce((a, b) => a + b, 0); } console.log(sum(1, 2, 3, 4)); // 10 ``` `...numbers` gathers every argument into a real array, unlike the array-like `arguments`. ### Spread vs rest and what it replaced | Feature | Spread | Rest | | --- | --- | --- | | What it does | Unpacks | Gathers | | Where it is used | In a function call, when building an array or object | In a function declaration or in destructuring | | Example | `[...arr]`, `{...obj}`, `fn(...args)` | `function fn(...args)`, `[a, ...rest]` | Before and after: | Before ES6 | With ES6 | | --- | --- | | `arr1.concat(arr2)` | `[...arr1, ...arr2]` | | `Object.assign({}, obj1, obj2)` | `{...obj1, ...obj2}` | | `Array.prototype.slice.call(arguments)` | `(...args) => {}` | Summary of the behaviour: | Context | Behaviour of `...` | Example | | --- | --- | --- | | Spread (unpacking) | Expands an array or object | `[...arr]`, `{...obj}`, `sum(...nums)` | | Rest (remainder) | Gathers the remaining elements | `[a, ...rest]`, `function fn(...args)` | ### Common mistakes 1. **Treating spread as a deep copy.** Spread and rest are shallow: nested objects and arrays are copied by reference, so changing a nested field in the copy is visible in the original. ```javascript const obj = { nested: { a: 1 } }; const copy = { ...obj }; copy.nested.a = 2; console.log(obj.nested.a); // 2, not 1 ``` A deep copy needs `structuredClone(obj)` or a manual walk of the structure. 2. **Using `...` outside a destructuring context.** `const ...rest = arr;` is a syntax error; the correct form is `const [a, ...rest] = arr;`. 3. **Putting rest anywhere but last.** `function fn(...args, last) {}` does not parse: a rest parameter must be the final one, because it swallows everything that is left. 4. **Forgetting key order in object spread.** `{ ...defaults, ...options }` and `{ ...options, ...defaults }` give different results, because the rightmost object wins. 5. **Confusing `...args` with `arguments`.** `arguments` is an array-like object that does not exist in arrow functions; a rest parameter always gives a real array with `map`, `filter` and `reduce`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.