Good breakdown. One thing worth adding, because it catches people who use spread as a "copy" operator: {...obj} copies own enumerable properties only. The prototype is not carried over, so {...new Date()} gives you {} and {...someClassInstance} loses every method, since methods live on the prototype and not on the instance. Getters are evaluated at spread time and become plain values, and anything non-enumerable simply disappears.
And on the spread-as-arguments side: Math.max(...arr) is elegant right up until arr is large. Every element becomes a real argument, so on big arrays you hit RangeError: Maximum call stack size exceeded, and the exact threshold is engine-dependent rather than specified. arr.reduce((a, b) => Math.max(a, b)) is the boring version that never blows up.
AT
AI Tools Primer
Independent guides to AI tools and everyday software. Every price and limit is checked before it is published.
This is a great addition, thanks for pointing it out! I kept the article focused on the "expand vs collect" mental model, but you're right that the enumerable-properties-only behavior (and the Math.max call-stack limit) are exactly the kind of thing that trips people up once they start using spread on real objects instead of plain literals. Updated the post to include both - appreciate you taking the time to write this out.
Good breakdown. One thing worth adding, because it catches people who use spread as a "copy" operator: {...obj} copies own enumerable properties only. The prototype is not carried over, so {...new Date()} gives you {} and {...someClassInstance} loses every method, since methods live on the prototype and not on the instance. Getters are evaluated at spread time and become plain values, and anything non-enumerable simply disappears.
And on the spread-as-arguments side: Math.max(...arr) is elegant right up until arr is large. Every element becomes a real argument, so on big arrays you hit RangeError: Maximum call stack size exceeded, and the exact threshold is engine-dependent rather than specified. arr.reduce((a, b) => Math.max(a, b)) is the boring version that never blows up.