Q1Write const copied = [...items];, then copied.push("X"). What happens to the original items?
Spread Syntax — Copying, Combining, and Overriding Settings
Use spread syntax to lay out array or object contents in place, copying and combining without changing the original.
Merge a list of in-stock products with a list of backordered ones into one. Layer only the fields a user changed on top of default settings. In cases like these, you build a new array or object with the contents laid out, while leaving the original data exactly as it was.
This article covers spread syntax for that, and which value wins when the same key shows up twice.
Laying Out Contents in Place — Spread Syntax
Want to merge a list of in-stock products with a list of backordered ones into one? Add them one at a time with push, and the original array gets rewritten. This is a case where you want to build a new array with the contents laid out, while leaving the original lists exactly as they were.
Spread syntax (writing ... before a value to lay out an array's or object's contents in place) lets you write const allItems = [...inStock, ...backOrder]; to build a new, combined array. Write just one, as in [...inStock], and that's a copy — a separate array with the same contents.
Objects work the same way, with { ...product }. Note this is a copy of only the first level — the behavior when there's an object or array nested inside is covered in the article on references and copying.
... plays a different role depending on where you write it. On the left side of =, it's rest, bundling up what's left. Inside [] or {} on the right side, it's spread, laying out contents. It's the same symbol, but bundling and spreading run in opposite directions.
const inStock = ["Wireless Mouse", "USB-C Hub"];
const backOrder = ["Monitor Arm"];
// Build a new array laying out both
const allItems = [...inStock, ...backOrder];
console.log(allItems.join(", ")); // Wireless Mouse, USB-C Hub, Monitor Arm
// The original array is untouched
console.log(inStock.length); // 2
// You can mix in individual values partway through
const featured = ["This Week's Pick", ...inStock];
console.log(featured.length); // 3
// Objects can be copied the same way
const product = { name: "USB-C Hub", price: 2480 };
const copied = { ...product };
console.log(copied.price); // 2480
Layering Settings — the Later One Wins
An app's settings are sometimes set up with a full round of defaults, then only the fields the user changed get overridden. Check and assign each changed field one at a time, though, and you'd need to add code every time a new setting appears.
Line up two object spreads, as in { ...defaultSettings, ...userSettings }, and a shared key gets overwritten by whichever value was written later. A key the user hasn't specified stays at its default.
The order you write them in becomes the priority directly, so put the defaults first and whatever you want to take priority after.
const defaultSettings = { theme: "light", itemsPerPage: 20, notifications: true };
const userSettings = { theme: "dark" };
const merged = { ...defaultSettings, ...userSettings };
console.log(merged.theme); // dark (the one written later wins)
console.log(merged.itemsPerPage); // 20 (missing on the user side, so the default stays)
// Reverse the order, and the default wins instead
const reversed = { ...userSettings, ...defaultSettings };
console.log(reversed.theme); // light
// Even an undefined value overrides, as long as the key exists on the later side
const partial = { theme: undefined };
const broken = { ...defaultSettings, ...partial };
console.log(broken.theme); // undefined
Even undefined Overrides
As long as the key exists on the side you're layering on top, it overrides — even if the value is undefined. Layer an unfilled field straight from a form on top like this, and the default disappears, replaced by undefined. For a field you only want to use when it actually has a value, check it one at a time, as in userSettings.theme ?? defaultSettings.theme.
Knowledge Check
Answer each question one by one.
Q2With const merged = { ...defaults, ...user };, what happens to a key that exists on both sides?
Q3The object you're layering on top has the key, but its value is undefined. What happens to the default?