{"id":"l-js-3-2","courseId":"javascript-fundamentals","lang":"en","kind":"lesson","summary":"Model real records as objects, read and update their properties, understand that objects are shared by reference, and copy, update and unpack them with spread and destructuring.","html":"<p>Until now an expense in Pocket was just a number. A real expense has several facts that belong together: what it was, how much, which category, when. Keeping those in separate arrays (<code dir=\"ltr\">labels[2]</code>, <code dir=\"ltr\">amounts[2]</code>, <code dir=\"ltr\">categories[2]</code>) works until one array gets sorted and the others do not. You need one value that holds them all: an <strong>object</strong>.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">Objects: named values together</h2>\n<p>An object is written with curly braces and contains <strong>properties</strong>, each a name and a value:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"0\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expense</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-1\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  category: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">};</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense.label);       </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// dot notation</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"amount\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]);   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// bracket notation</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense.note);        </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// missing property: undefined</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>Dot notation is the everyday way to read a property. Brackets do the same job, but evaluate whatever is inside them, which you need when the property name is in a variable: <code dir=\"ltr\">const field = &quot;category&quot;; expense[field]</code>. Reading a property that does not exist gives <code dir=\"ltr\">undefined</code>, not an error.</p>\n<p>You can add, change and remove properties after creation:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"1\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expense</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">expense.category </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// add</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">expense.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 500</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;        </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// change</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">delete</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense.category;     </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// remove</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(Object.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">keys</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense), Object.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">values</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense));</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>When a variable already has the name you want for a property, you can write it once. <code dir=\"ltr\">{ label, amount }</code> is shorthand for <code dir=\"ltr\">{ label: label, amount: amount }</code>, and you will see it constantly in real code:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"2\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> label</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"Bus\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> amount</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 270</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expense</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { label, amount, category: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"travel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense);</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<p><code dir=\"ltr\">Object.keys</code> and <code dir=\"ltr\">Object.values</code> give you arrays of the names and the values, and <code dir=\"ltr\">Object.entries</code> gives pairs, so <code dir=\"ltr\">for (const [key, value] of Object.entries(expense))</code> loops over every property.</p>\n<p>Pocket’s data is now an <strong>array of objects</strong>, the most common shape of data in JavaScript, and everything from the last lesson still applies:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"3\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expenses</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-1\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, category: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-2\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Train\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1220</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, category: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"travel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-3\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Lunch\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1350</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, category: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">];</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> food</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">filter</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> e.category </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">===</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(food.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> e.label));</span></span></code></pre><div class=\"run-output\" data-run-output=\"3\" hidden></div></div>\n<h2 id=\"sec-2\" tabindex=\"-1\">References: two names, one object</h2>\n<p>Here is the most important thing to understand about objects and arrays. A variable does not hold the object; it holds a <strong>reference</strong> to it, like an address. Copying the variable copies the address:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"4\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> original</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> alias</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> original;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">alias.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 999</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(original.amount);       </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// 999</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(alias </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">===</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> original);    </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// true: the same object</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ a: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">===</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { a: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }); </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// false: two different objects</span></span></code></pre><div class=\"run-output\" data-run-output=\"4\" hidden></div></div>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 660 230\" role=\"img\" aria-labelledby=\"l-js-3-2-t1\"><defs><marker id=\"arrow-l-js-3-2-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-js-3-2-t1\">The names original and alias both point to the same object, so a change through alias shows through original. The name copy points to a separate new object created with spread.</title>\n  <rect class=\"d-box-primary\" x=\"20\" y=\"30\" width=\"130\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"85\" y=\"57\" text-anchor=\"middle\">original</text>\n  <rect class=\"d-box-primary\" x=\"20\" y=\"100\" width=\"130\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"85\" y=\"127\" text-anchor=\"middle\">alias</text>\n  <rect class=\"d-box\" x=\"260\" y=\"50\" width=\"260\" height=\"70\" rx=\"12\"/>\n  <text class=\"d-code\" x=\"390\" y=\"90\" text-anchor=\"middle\">{ label: \"Coffee\", amount: 999 }</text>\n  <path class=\"d-arrow\" d=\"M150 52 L256 75\" marker-end=\"url(#arrow-l-js-3-2-1)\"/>\n  <path class=\"d-arrow\" d=\"M150 122 L256 98\" marker-end=\"url(#arrow-l-js-3-2-1)\"/>\n  <rect class=\"d-box-primary\" x=\"20\" y=\"170\" width=\"130\" height=\"44\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"85\" y=\"197\" text-anchor=\"middle\">copy</text>\n  <rect class=\"d-box-success\" x=\"260\" y=\"160\" width=\"260\" height=\"60\" rx=\"12\"/>\n  <text class=\"d-code\" x=\"390\" y=\"195\" text-anchor=\"middle\">{ label: \"Coffee\", amount: 450 }</text>\n  <path class=\"d-arrow\" d=\"M150 192 L256 192\" marker-end=\"url(#arrow-l-js-3-2-1)\"/>\n  <text class=\"d-label-muted\" x=\"600\" y=\"90\" text-anchor=\"middle\">one object</text>\n  <text class=\"d-label-muted\" x=\"600\" y=\"195\" text-anchor=\"middle\">a new one</text>\n</svg><figcaption>Assigning copies the reference; spread creates a new object</figcaption></figure>\n<p><code dir=\"ltr\">===</code> on objects compares references, not contents. Two objects that look identical are still two different objects.</p>\n<p>This matters because functions receive references too. If a function changes an object it was given, the caller’s object changes:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"5\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"5\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> applyDiscount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  expense.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Math.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.9</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> lunch</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Lunch\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1350</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> discounted</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> applyDiscount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(lunch);</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(discounted.amount, lunch.amount); </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// both 1215</span></span></code></pre><div class=\"run-output\" data-run-output=\"5\" hidden></div></div>\n<p>The function looks as if it returns a discounted version, but it quietly rewrote the original as well. Somewhere else, a total that included <code dir=\"ltr\">lunch</code> is now wrong, and nothing on screen says why. That is how bugs like “I only displayed the expenses, why did their amounts change?” happen. The fix is to build a new object instead of changing the one you were given, and spread makes that easy.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">Spread: copy and update without mutating</h2>\n<p><strong>Spread syntax</strong>, three dots, copies all the properties of an object (or items of an array) into a new one:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"6\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"6\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expense</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-1\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> updated</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">expense, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">500</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(expense.amount, updated.amount);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> list</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [expense];</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> longer</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">list, { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-2\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Bus\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">270</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }];</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(list.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">length</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, longer.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">length</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);</span></span></code></pre><div class=\"run-output\" data-run-output=\"6\" hidden></div></div>\n<p>In <code dir=\"ltr\">{ ...expense, amount: 500 }</code>, properties are copied in order and the later <code dir=\"ltr\">amount</code> overwrites the copied one. You get a new object, and the original is untouched. Combined with <code dir=\"ltr\">map</code>, this is the standard way to change one item in a list without mutating anything:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"7\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"7\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expenses</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-1\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  { id: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"exp-2\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Bus\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">270</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> },</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">];</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> fixed</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expenses.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">map</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">((</span><span style=\"color:#953800;--shiki-dark:#FFA657\">e</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=></span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (e.id </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">===</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"exp-2\"</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> ?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">...</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">e, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">300</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> e));</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(fixed[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].amount, expenses[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].amount);</span></span></code></pre><div class=\"run-output\" data-run-output=\"7\" hidden></div></div>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Expecting spread to copy deeply</span></p>\n<p>Spread is a <strong>shallow</strong> copy: it copies the top-level properties. If a property is itself an object, such as <code dir=\"ltr\">tags: [&quot;work&quot;]</code>, the copy and the original share that inner array, and pushing to one changes both. When you need a fully independent copy of nested data, use <code dir=\"ltr\">structuredClone(value)</code>.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">Destructuring: unpacking into variables</h2>\n<p><strong>Destructuring</strong> pulls properties out of an object into variables of the same name:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"8\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"8\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> expense</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Train\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1220</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, category: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"travel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">label</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">note</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"no note\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> } </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> expense;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(label, amount, note);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">first</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">second</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"food\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"travel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"fun\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">];</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(first, second);</span></span></code></pre><div class=\"run-output\" data-run-output=\"8\" hidden></div></div>\n<p>The <code dir=\"ltr\">= &quot;no note&quot;</code> is a default, used when the property is missing or <code dir=\"ltr\">undefined</code>. For arrays, destructuring goes by position instead of name.</p>\n<p>Destructuring is most useful in function parameters, where it documents exactly which properties a function needs:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-run=\"js\" data-index=\"9\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"js\" data-index=\"9\" aria-label=\"Run this example\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>Run</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> describe</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ </span><span style=\"color:#953800;--shiki-dark:#FFA657\">label</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">category</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"other\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }) {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> `${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">label</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">}: $${</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">(</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">amount</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> /</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 100</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">).</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">toFixed</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">} (${</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">category</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">})`</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">describe</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({ label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Train\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1220</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }));</span></span></code></pre><div class=\"run-output\" data-run-output=\"9\" hidden></div></div>\n<p>Compare it with the version without destructuring, which repeats <code dir=\"ltr\">expense.</code> on every line and hides which properties matter until you read the whole body. With destructuring, the first line of the function is its contract: give me something with a label, an amount, and optionally a category. Callers can pass a full expense object with ten other properties; the function simply ignores the rest.</p>\n<p>The <code dir=\"ltr\">...</code> also works in reverse, as <strong>rest</strong>: <code dir=\"ltr\">const { id, ...details } = expense</code> puts <code dir=\"ltr\">id</code> in its own variable and every other property in a new object called <code dir=\"ltr\">details</code>. It is a neat way to drop a property without mutating the original: everything you did not name ends up in the new object.</p>\n<p>Pocket now has realistic data. Next you summarise it: totals per category, and lists sorted by amount.</p>\n","toc":[{"id":"sec-1","text":"Objects: named values together","level":2},{"id":"sec-2","text":"References: two names, one object","level":2},{"id":"sec-3","text":"Spread: copy and update without mutating","level":2},{"id":"sec-4","text":"Destructuring: unpacking into variables","level":2}],"takeaways":["An object groups named values (properties); read them with dot notation, or with brackets when the property name is in a variable.","Objects and arrays are shared by reference, so two names can point at the same object and a change through one is visible through the other.","Spread (<code dir=\"ltr\">{ ...expense, amount: 500 }</code>, <code dir=\"ltr\">[...list, item]</code>) makes a new, shallow copy, which is how you update data without mutating it.","Destructuring (<code dir=\"ltr\">const { label, amount } = expense</code>) pulls properties into variables, and works in function parameters with defaults."],"further":[{"title":"Working with objects (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_objects"},{"title":"Destructuring (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring"},{"title":"Spread syntax (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"}],"quiz":[{"q":"<p>What does this log?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"js\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JavaScript</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> a</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { label: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, amount: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">450</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> };</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">const</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> b</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> a;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">b.amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 500</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">console.</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">log</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(a.amount);</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">500</code>, because <code dir=\"ltr\">a</code> and <code dir=\"ltr\">b</code> point at the same object.","why":"Correct. There is only one object. Changing it through <code dir=\"ltr\">b</code> is visible through <code dir=\"ltr\">a</code>."},{"text":"<code dir=\"ltr\">450</code>, because <code dir=\"ltr\">b</code> is a copy of <code dir=\"ltr\">a</code>.","why":"Assigning an object to another name copies the reference, not the object. Both names point at the same object."},{"text":"A TypeError, because <code dir=\"ltr\">a</code> is a <code dir=\"ltr\">const</code>.","why":"<code dir=\"ltr\">const</code> stops <code dir=\"ltr\">a</code> from being re-pointed. Changing a property of the object it points at is allowed."}],"answer":0},{"q":"<p><code dir=\"ltr\">const updated = { ...expense, amount: 500 };</code> What is true afterwards?</p>","options":[{"text":"<code dir=\"ltr\">expense.amount</code> is now 500.","why":"Spread builds a brand-new object. The original is not touched."},{"text":"<code dir=\"ltr\">updated</code> is the same object as <code dir=\"ltr\">expense</code>.","why":"<code dir=\"ltr\">{ ... }</code> always creates a new object, so <code dir=\"ltr\">updated === expense</code> is false."},{"text":"<code dir=\"ltr\">updated</code> has every property of <code dir=\"ltr\">expense</code>, with <code dir=\"ltr\">amount</code> replaced by 500.","why":"Correct. Properties are copied in order, and a later <code dir=\"ltr\">amount</code> overwrites the copied one."}],"answer":2},{"q":"<p>Given <code dir=\"ltr\">const expense = { label: &quot;Bus&quot;, amount: 270 };</code>, what does <code dir=\"ltr\">const { label, category = &quot;other&quot; } = expense;</code> give you?</p>","options":[{"text":"<code dir=\"ltr\">label</code> is “Bus” and <code dir=\"ltr\">category</code> is “other”.","why":"Correct. <code dir=\"ltr\">label</code> is copied from the object, and <code dir=\"ltr\">category</code> does not exist on it, so the default is used."},{"text":"<code dir=\"ltr\">label</code> is “Bus” and <code dir=\"ltr\">category</code> is undefined.","why":"That would be true without the default. <code dir=\"ltr\">= &quot;other&quot;</code> applies when the property is missing."},{"text":"It throws, because <code dir=\"ltr\">category</code> is not a property of <code dir=\"ltr\">expense</code>.","why":"Destructuring a missing property never throws; it gives <code dir=\"ltr\">undefined</code>, or the default if you supplied one."}],"answer":0},{"q":"<p>You have <code dir=\"ltr\">const key = &quot;category&quot;;</code>. How do you read <code dir=\"ltr\">expense.category</code> using <code dir=\"ltr\">key</code>?</p>","options":[{"text":"<code dir=\"ltr\">expense.key</code>","why":"Dot notation uses the literal name after the dot, so this looks for a property called “key”."},{"text":"<code dir=\"ltr\">expense[key]</code>","why":"Correct. Brackets evaluate the expression inside, so <code dir=\"ltr\">expense[key]</code> reads the property named by the value of <code dir=\"ltr\">key</code>."},{"text":"<code dir=\"ltr\">expense[&quot;key&quot;]</code>","why":"The quotes make it the literal string “key”, the same as <code dir=\"ltr\">expense.key</code>."}],"answer":1}],"exercise":{"kind":"web","mode":"js","starter":{"js":"const expenses = [\n  { id: \"exp-1\", label: \"Coffee\", amount: 450, category: \"food\" },\n  { id: \"exp-2\", label: \"Train\", amount: 1220, category: \"travel\" },\n];\n\n// Return a NEW array with the expense added at the end\nfunction addExpense(list, expense) {\n  list.push(expense);\n  return list;\n}\n\n// Return a NEW array where the expense with this id has the new amount\nfunction updateAmount(list, id, amount) {\n  const found = list.find((e) => e.id === id);\n  found.amount = amount;\n  return list;\n}\n\n// \"Train: $12.20 (travel)\"; category defaults to \"other\"\nfunction describe(expense) {\n  return expense.label;\n}\n\nconsole.log(describe(expenses[1]));\n"},"solution":{"js":"const expenses = [\n  { id: \"exp-1\", label: \"Coffee\", amount: 450, category: \"food\" },\n  { id: \"exp-2\", label: \"Train\", amount: 1220, category: \"travel\" },\n];\n\nfunction addExpense(list, expense) {\n  return [...list, expense];\n}\n\nfunction updateAmount(list, id, amount) {\n  return list.map((e) => (e.id === id ? { ...e, amount } : e));\n}\n\nfunction describe({ label, amount, category = \"other\" }) {\n  return `${label}: $${(amount / 100).toFixed(2)} (${category})`;\n}\n\nconsole.log(describe(expenses[1]));\n"},"checks":[{"id":"add","test":"const list = [{ id: 'a', label: 'A', amount: 1 }];\nconst item = { id: 'b', label: 'B', amount: 2 };\nconst out = addExpense(list, item);\nreturn Array.isArray(out) && out.length === 2 && out[1] === item && out[0] === list[0];\n"},{"id":"add-pure","test":"const list = [{ id: 'a', label: 'A', amount: 1 }];\nconst out = addExpense(list, { id: 'b', label: 'B', amount: 2 });\nreturn list.length === 1 && out !== list;\n"},{"id":"update","test":"const list = [{ id: 'a', label: 'A', amount: 1 }, { id: 'b', label: 'B', amount: 2 }];\nconst out = updateAmount(list, 'b', 300);\nreturn Array.isArray(out) && out.length === 2 && out[1].amount === 300 && out[1].label === 'B' && out[1].id === 'b' && out[0].amount === 1;\n"},{"id":"update-pure","test":"const list = [{ id: 'a', label: 'A', amount: 1 }, { id: 'b', label: 'B', amount: 2 }];\nconst out = updateAmount(list, 'b', 300);\nreturn list[1].amount === 2 && out !== list && out[1] !== list[1];\n"},{"id":"describe","test":"return describe({ label: 'Train', amount: 1220, category: 'travel' }) === 'Train: $12.20 (travel)' && describe({ label: 'Gift', amount: 5000 }) === 'Gift: $50.00 (other)';\n"}],"title":"Update expenses without mutating them","prompt":"<p>The starter’s functions change the arrays and objects they are given, so the caller’s data changes behind its back. Rewrite them to return new values instead:</p>\n<ul>\n<li><code dir=\"ltr\">addExpense(list, expense)</code> returns a <strong>new</strong> array with <code dir=\"ltr\">expense</code> at the end.</li>\n<li><code dir=\"ltr\">updateAmount(list, id, amount)</code> returns a <strong>new</strong> array in which the expense with that <code dir=\"ltr\">id</code> is a <strong>new</strong> object with the new <code dir=\"ltr\">amount</code>. Other expenses stay as they are, and nothing in <code dir=\"ltr\">list</code> changes.</li>\n<li><code dir=\"ltr\">describe(expense)</code> returns a string like <code dir=\"ltr\">&quot;Train: $12.20 (travel)&quot;</code>, using <code dir=\"ltr\">&quot;other&quot;</code> when there is no category. Destructure the parameter.</li>\n</ul>\n","hints":["Spread an array into a new one: <code dir=\"ltr\">[...list, expense]</code>.","For the update, <code dir=\"ltr\">map</code> over the list and return either <code dir=\"ltr\">{ ...e, amount }</code> or <code dir=\"ltr\">e</code> unchanged, depending on whether <code dir=\"ltr\">e.id === id</code>.","Destructure with a default in the parameter list: <code dir=\"ltr\">function describe({ label, amount, category = &quot;other&quot; })</code>."],"explanation":"<p><code dir=\"ltr\">[...list, expense]</code> copies the references of the existing items into a new array and adds one more, so the caller’s array keeps its length. In <code dir=\"ltr\">updateAmount</code>, <code dir=\"ltr\">map</code> already builds a new array; for the matching item you return <code dir=\"ltr\">{ ...e, amount }</code>, a new object with every property of <code dir=\"ltr\">e</code> and the new amount (the shorthand <code dir=\"ltr\">amount</code> means <code dir=\"ltr\">amount: amount</code>). Unchanged items are returned as they are, which is safe because nothing modifies them. In <code dir=\"ltr\">describe</code>, destructuring in the parameter list documents the three properties the function needs, and the default covers expenses without a category.</p>\n","checkLabels":{"add":"<code dir=\"ltr\">addExpense</code> returns the list with the new expense at the end","add-pure":"<code dir=\"ltr\">addExpense</code> leaves the original array unchanged","update":"<code dir=\"ltr\">updateAmount</code> changes the amount of the matching expense","update-pure":"<code dir=\"ltr\">updateAmount</code> leaves the original array and objects unchanged","describe":"<code dir=\"ltr\">describe</code> formats the expense, defaulting the category to “other”"}},"words":718,"readMinutes":3}