Where ... appears decides which one it is.
Spread is an expression: it expands something into individual items.
- In a call or
new, or inside an array literal, it iterates its operand with the iteration protocol:f(...args),[...a, ...b]. The operand must be iterable (arrays, strings,Set,Map, generators); a plain object throwsTypeError. - In an object literal,
{ ...src }performsCopyDataProperties: it readssrc's own enumerable properties (string and symbol keys), usingGet, so getters run and the copy gets plain data properties. Inherited and non-enumerable properties are skipped,nullandundefinedare ignored, and a string spreads as index keys. Later keys overwrite earlier ones, so{ ...defaults, ...overrides }letsoverrideswin.
Rest is a binding: it collects the remainder into a new value.
- In a parameter list,
(first, ...others)gives a real array of the extra arguments. It replacesarguments, works in arrow functions, and is not counted infn.length. - In an array pattern,
[head, ...tail]drains the iterator into an array. - In an object pattern,
{ a, ...others }copies every own enumerable property except the listed ones into a new plain object.
A rest element must be last and appear once (SyntaxError otherwise), and it takes no default.
Both are shallow: nested objects are copied by reference. Spread is a copy, not a clone, and it doesn't preserve the prototype, descriptors, or non-enumerable properties.