[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"playground-immutable-array-methods":32},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"slug":33,"title":34,"summary":35,"html":36,"css":37,"js":38,"config":39,"doc":41},"immutable-array-methods","sort() vs toSorted() — watch the reference",null,"\u003Cdiv class=\"wrap\">\n    \u003Ch1>🎮 sort() vs toSorted(): watch the reference\u003C\u002Fh1>\n    \u003Cp class=\"sub\">\n      Classic methods (\u003Ccode>sort\u003C\u002Fcode>, \u003Ccode>reverse\u003C\u002Fcode>, \u003Ccode>splice\u003C\u002Fcode>) mutate the array and hand back the\n      \u003Cstrong>same\u003C\u002Fstrong> reference — so React compares by identity, sees no change, and \u003Cstrong>skips the re-render\u003C\u002Fstrong>.\n      ES2023's \u003Ccode>toSorted\u003C\u002Fcode>, \u003Ccode>toReversed\u003C\u002Fcode>, \u003Ccode>toSpliced\u003C\u002Fcode>, \u003Ccode>with\u003C\u002Fcode> return a\n      \u003Cstrong>new\u003C\u002Fstrong> array. Click one and watch \u003Ccode>result === original\u003C\u002Fcode> flip.\n    \u003C\u002Fp>\n\n    \u003Cdiv class=\"panel\">\n      \u003Ch2>1 · Run a method on the array\u003C\u002Fh2>\n      \u003Cdiv class=\"cols\">\n        \u003Cdiv class=\"col\">\n          \u003Cdiv class=\"colhead bad\">⚠️ Mutating — returns the same array\u003C\u002Fdiv>\n          \u003Cbutton class=\"op bad\" data-op=\"sort\">sort((a,b) =&gt; b.priority - a.priority)\u003C\u002Fbutton>\n          \u003Cbutton class=\"op bad\" data-op=\"reverse\">reverse()\u003C\u002Fbutton>\n          \u003Cbutton class=\"op bad\" data-op=\"splice\">splice(1, 1)\u003C\u002Fbutton>\n        \u003C\u002Fdiv>\n        \u003Cdiv class=\"col\">\n          \u003Cdiv class=\"colhead good\">✓ Immutable — returns a new array\u003C\u002Fdiv>\n          \u003Cbutton class=\"op good\" data-op=\"toSorted\">toSorted((a,b) =&gt; b.priority - a.priority)\u003C\u002Fbutton>\n          \u003Cbutton class=\"op good\" data-op=\"toReversed\">toReversed()\u003C\u002Fbutton>\n          \u003Cbutton class=\"op good\" data-op=\"toSpliced\">toSpliced(1, 1)\u003C\u002Fbutton>\n          \u003Cdiv class=\"withrow\">\n            \u003Clabel>with(\n              \u003Cselect id=\"withIdx\" aria-label=\"index to replace\">\u003C\u002Fselect>,\n              priority\n              \u003Cinput id=\"withVal\" type=\"number\" min=\"1\" max=\"9\" value=\"9\" aria-label=\"new priority\" \u002F>\n              )\u003C\u002Flabel>\n            \u003Cbutton class=\"op good\" data-op=\"with\">Apply with()\u003C\u002Fbutton>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\n      \u003Cdiv class=\"resetrow\">\u003Cbutton id=\"reset\" class=\"ghost\">↺ Reset array\u003C\u002Fbutton>\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n\n    \u003Cdiv class=\"panel\">\n      \u003Ch2>2 · What just happened\u003C\u002Fh2>\n      \u003Cdiv class=\"empty\" id=\"empty\">\n        Click a method above. You'll see the array it returned, whether the original was\n        mutated, whether \u003Ccode style=\"color:var(--accent)\">result === original\u003C\u002Fcode>, and — the whole point —\n        whether React would re-render.\n      \u003C\u002Fdiv>\n\n      \u003Cdiv id=\"resultBody\" hidden>\n        \u003Cdiv class=\"method\">\u003Ccode id=\"methodCode\">\u003C\u002Fcode>\u003C\u002Fdiv>\n\n        \u003Cdiv class=\"arrays\">\n          \u003Cdiv class=\"arrcard\">\n            \u003Cdiv class=\"arrhead\">\u003Cspan>Original array\u003C\u002Fspan>\u003Cspan class=\"badge\" id=\"origBadge\">array\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cul class=\"chips\" id=\"origList\">\u003C\u002Ful>\n          \u003C\u002Fdiv>\n          \u003Cdiv class=\"rel\" id=\"rel\">\u003Cspan class=\"op-sym\" id=\"relSym\">===\u003C\u002Fspan>\u003Cspan class=\"op-cap\" id=\"relCap\">same array\u003C\u002Fspan>\u003C\u002Fdiv>\n          \u003Cdiv class=\"arrcard\">\n            \u003Cdiv class=\"arrhead\">\u003Cspan>Method returned\u003C\u002Fspan>\u003Cspan class=\"badge\" id=\"resBadge\">array\u003C\u002Fspan>\u003C\u002Fdiv>\n            \u003Cul class=\"chips\" id=\"resList\">\u003C\u002Ful>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003Cdiv class=\"facts\">\n          \u003Cdiv class=\"fact\">\u003Cspan>result === original\u003C\u002Fspan>\u003Cb id=\"factRef\">\u003C\u002Fb>\u003C\u002Fdiv>\n          \u003Cdiv class=\"fact\">\u003Cspan>original mutated?\u003C\u002Fspan>\u003Cb id=\"factMut\">\u003C\u002Fb>\u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n\n        \u003Cdiv class=\"rerender\" id=\"rerender\">\u003C\u002Fdiv>\n        \u003Cp class=\"status\" id=\"status\">\u003C\u002Fp>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>",":root {\n    --bg: #0d1117; --panel: #161b22; --ink: #e8ebf2; --muted: #9aa4b2;\n    --accent: #7c9cff; --good: #3fb950; --bad: #f0883e; --line: #232a35;\n    font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n  }\n  * { box-sizing: border-box; }\n  body { margin: 0; background: var(--bg); color: var(--ink); min-height: 100vh;\n    display: flex; align-items: flex-start; justify-content: center; padding: 18px; }\n  .wrap { width: 100%; max-width: 720px; }\n\n  h1 { font-size: 1.2rem; margin: 0 0 3px; letter-spacing: -0.01em; }\n  .sub { color: var(--muted); font-size: .9rem; margin: 0 0 14px; line-height: 1.45; }\n  .sub code, .sub strong { color: var(--accent); }\n  .sub code { background: #ffffff10; padding: 1px 5px; border-radius: 5px; font-size: .85em; }\n  .sub strong { font-weight: 700; }\n\n  .panel { background: var(--panel); border: 1px solid var(--line);\n    border-radius: 14px; padding: 16px; margin-bottom: 14px; }\n  .panel h2 { font-size: .72rem; text-transform: uppercase; letter-spacing: .07em;\n    color: var(--muted); margin: 0 0 12px; font-weight: 700; }\n\n  \u002F* ---- Operation columns ---- *\u002F\n  .cols { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }\n  .col { border: 1px solid var(--line); border-radius: 11px; padding: 12px; background: #0b0e14;\n    display: flex; flex-direction: column; gap: 8px; }\n  .colhead { font-size: .72rem; font-weight: 700; letter-spacing: .02em; margin-bottom: 2px;\n    display: flex; align-items: center; gap: 6px; }\n  .colhead.bad { color: var(--bad); }\n  .colhead.good { color: var(--good); }\n\n  button { font: inherit; font-weight: 600; border-radius: 10px; cursor: pointer;\n    border: 1px solid var(--line); background: transparent; color: var(--ink); padding: 9px 12px; }\n  button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n  .op { text-align: left; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n    font-size: .86rem; transition: transform .06s ease, background .15s ease; }\n  .op:hover { transform: translateY(-1px); }\n  .op:active { transform: translateY(0); }\n  .op.bad  { border-color: #f0883e55; color: #ffb98a; background: #f0883e12; }\n  .op.bad:hover  { background: #f0883e22; }\n  .op.good { border-color: #3fb95055; color: #86e29b; background: #3fb95012; }\n  .op.good:hover { background: #3fb95022; }\n\n  .withrow { border-top: 1px dashed var(--line); margin-top: 4px; padding-top: 10px;\n    display: flex; flex-direction: column; gap: 8px; }\n  .withrow label { color: var(--muted); font-size: .82rem; display: flex; flex-wrap: wrap;\n    align-items: center; gap: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }\n  select, input[type=number] { font: inherit; font-size: .82rem; background: #11161f; color: var(--ink);\n    border: 1px solid var(--line); border-radius: 7px; padding: 4px 6px; }\n  input[type=number] { width: 52px; }\n  select:focus-visible, input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }\n\n  .resetrow { margin-top: 12px; }\n  .ghost { color: var(--ink); border: 1px solid var(--line); background: transparent; font-size: .85rem; }\n  .ghost:hover { background: #ffffff0a; }\n\n  \u002F* ---- Result \u002F verdict ---- *\u002F\n  .empty { color: var(--muted); font-size: .86rem; line-height: 1.5; }\n\n  .method { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n    font-size: .84rem; color: var(--ink); background: #0b0e14; border: 1px solid var(--line);\n    border-radius: 10px; padding: 10px 12px; margin-bottom: 14px; overflow-x: auto; white-space: nowrap; }\n  .method .cmt { color: #6b7688; }\n\n  .arrays { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: stretch;\n    margin-bottom: 14px; }\n  .arrcard { border: 1px solid var(--line); border-radius: 11px; padding: 10px; background: #0b0e14; }\n  .arrhead { display: flex; justify-content: space-between; align-items: center; gap: 6px;\n    margin-bottom: 8px; }\n  .arrhead > span:first-child { font-size: .72rem; color: var(--muted); font-weight: 700;\n    text-transform: uppercase; letter-spacing: .04em; }\n  .badge { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .74rem;\n    font-weight: 700; padding: 2px 8px; border-radius: 999px; white-space: nowrap;\n    border: 1px solid var(--line); color: var(--ink); background: #ffffff08; }\n  .badge.same { color: var(--bad); border-color: #f0883e55; background: #f0883e14; }\n  .badge.fresh { color: var(--good); border-color: #3fb95055; background: #3fb95014; }\n\n  .chips { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }\n  .chip { display: flex; justify-content: space-between; align-items: center; gap: 8px;\n    background: #11161f; border: 1px solid var(--line); border-radius: 8px; padding: 5px 9px;\n    font-size: .82rem; animation: pop .28s ease; }\n  .chip .ctitle { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n  .chip .pill { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .72rem;\n    font-weight: 700; color: var(--accent); background: #7c9cff1a; border-radius: 6px; padding: 1px 6px; }\n  @keyframes pop { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }\n\n  .rel { align-self: center; text-align: center; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }\n  .rel .op-sym { font-size: 1.1rem; font-weight: 800; display: block; }\n  .rel .op-cap { font-size: .66rem; text-transform: uppercase; letter-spacing: .04em; margin-top: 3px; }\n  .rel.same { color: var(--bad); }\n  .rel.fresh { color: var(--good); }\n\n  .facts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }\n  .fact { background: #0b0e14; border: 1px solid var(--line); border-radius: 10px; padding: 9px 12px;\n    display: flex; flex-direction: column; gap: 3px; }\n  .fact > span { font-size: .72rem; color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }\n  .fact > b { font-size: 1.05rem; font-weight: 800; }\n  .fact .t { color: var(--bad); }   \u002F* true \u002F yes (in the \"bad for React\" sense) *\u002F\n  .fact .f { color: var(--good); }  \u002F* false \u002F no *\u002F\n\n  .rerender { border-radius: 11px; padding: 12px 14px; font-weight: 700; font-size: .92rem;\n    display: flex; align-items: center; gap: 9px; margin-bottom: 10px; }\n  .rerender.stale { color: #ffcda6; background: #f0883e16; border: 1px solid #f0883e55; }\n  .rerender.fresh { color: #9fe6b0; background: #3fb95016; border: 1px solid #3fb95055; }\n  .rerender.pulse { animation: flash .5s ease; }\n  @keyframes flash { 0% { filter: brightness(1.6); } 100% { filter: brightness(1); } }\n\n  .status { font-size: .84rem; line-height: 1.55; color: var(--muted); margin: 0; }\n  .status code { color: var(--ink); background: #ffffff10; padding: 1px 5px; border-radius: 5px;\n    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .82em; }\n  .status .hot { color: var(--bad); font-weight: 700; }\n  .status .cool { color: var(--good); font-weight: 700; }\n\n  @media (max-width: 560px) {\n    .cols { grid-template-columns: 1fr; }\n    .arrays { grid-template-columns: 1fr; }\n    .rel { transform: rotate(90deg); }\n    .facts { grid-template-columns: 1fr; }\n  }","\"use strict\";\n  const $ = (id) => document.getElementById(id);\n\n  \u002F\u002F Each array OBJECT gets a stable short \"hash\" tied to its identity — exactly\n  \u002F\u002F how React thinks. Same reference => same badge. New array => new badge.\n  const ids = new WeakMap();\n  const idOf = (arr) => {\n    if (!ids.has(arr)) ids.set(arr, \"#\" + Math.random().toString(16).slice(2, 5));\n    return ids.get(arr);\n  };\n\n  const cmp = (a, b) => b.priority - a.priority;\n  const START = () => ([\n    { id: 1, title: \"Review PR\",      priority: 2 },\n    { id: 2, title: \"Fix regression\", priority: 5 },\n    { id: 3, title: \"Update docs\",    priority: 1 },\n    { id: 4, title: \"Ship release\",   priority: 3 },\n  ]);\n\n  \u002F\u002F The single array React \"holds as state\". Mutating ops change it in place\n  \u002F\u002F (and persist until Reset); immutable ops leave it alone.\n  let original = START();\n\n  const snap = (arr) => arr.map((t) => t.id + \":\" + t.priority).join(\"|\");\n\n  const esc = (s) => String(s).replace(\u002F[&\u003C>]\u002Fg, (c) => ({ \"&\": \"&amp;\", \"\u003C\": \"&lt;\", \">\": \"&gt;\" }[c]));\n  const chipHtml = (t) =>\n    `\u003Cli class=\"chip\">\u003Cspan class=\"ctitle\">${esc(t.title)}\u003C\u002Fspan>\u003Cspan class=\"pill\">P${t.priority}\u003C\u002Fspan>\u003C\u002Fli>`;\n  const renderList = (el, arr) => { el.innerHTML = arr.map(chipHtml).join(\"\"); };\n\n  function refreshWithIdx() {\n    const sel = $(\"withIdx\");\n    sel.innerHTML = original\n      .map((t, i) => `\u003Coption value=\"${i}\">${i} — ${esc(t.title)}\u003C\u002Foption>`)\n      .join(\"\");\n  }\n  refreshWithIdx();\n\n  const METHOD_CODE = {\n    sort:       `tasks.\u003Cb>sort\u003C\u002Fb>((a, b) =&gt; b.priority - a.priority)`,\n    reverse:    `tasks.\u003Cb>reverse\u003C\u002Fb>()`,\n    splice:     `tasks.\u003Cb>splice\u003C\u002Fb>(1, 1)`,\n    toSorted:   `tasks.\u003Cb>toSorted\u003C\u002Fb>((a, b) =&gt; b.priority - a.priority)`,\n    toReversed: `tasks.\u003Cb>toReversed\u003C\u002Fb>()`,\n    toSpliced:  `tasks.\u003Cb>toSpliced\u003C\u002Fb>(1, 1)`,\n    with:       (i, v) => `tasks.\u003Cb>with\u003C\u002Fb>(${i}, { ...tasks[${i}], priority: ${v} })`,\n  };\n\n  function run(op) {\n    const before = snap(original);\n    let result, note = \"\";\n\n    if (op === \"sort\")            { original.sort(cmp);    result = original; }\n    else if (op === \"reverse\")    { original.reverse();    result = original; }\n    else if (op === \"splice\")     {\n      const removed = original.splice(1, 1);\n      note = `Heads up: \u003Ccode>splice()\u003C\u002Fcode> actually returns the \u003Cem>removed\u003C\u002Fem> item — ` +\n             `[${removed.map((t) => '\"' + esc(t.title) + '\"').join(\", \")}] — not the array. ` +\n             `You keep mutating and re-using the original.`;\n      result = original;\n    }\n    else if (op === \"toSorted\")   { result = original.toSorted(cmp); }\n    else if (op === \"toReversed\") { result = original.toReversed(); }\n    else if (op === \"toSpliced\")  { result = original.toSpliced(1, 1); }\n    else if (op === \"with\") {\n      const i = Number($(\"withIdx\").value);\n      const v = Math.max(1, Math.min(9, Number($(\"withVal\").value) || 1));\n      result = original.with(i, { ...original[i], priority: v });\n      render(op, result, before, i, v, note);\n      return;\n    }\n    render(op, result, before, null, null, note);\n  }\n\n  function render(op, result, before, i, v, note) {\n    const sameRef = result === original;           \u002F\u002F identity check — the star\n    const mutated = snap(original) !== before;      \u002F\u002F did the original change?\n    const reRender = !sameRef;                       \u002F\u002F React bails out if same ref\n\n    \u002F\u002F Method call line\n    const code = typeof METHOD_CODE[op] === \"function\" ? METHOD_CODE[op](i, v) : METHOD_CODE[op];\n    $(\"methodCode\").innerHTML = `const result = ${code};`;\n\n    \u002F\u002F Two arrays + their identity badges\n    renderList($(\"origList\"), original);\n    renderList($(\"resList\"), result);\n    const origBadge = $(\"origBadge\"), resBadge = $(\"resBadge\");\n    origBadge.textContent = \"array \" + idOf(original);\n    resBadge.textContent = \"array \" + idOf(result);\n    origBadge.className = \"badge \" + (sameRef ? \"same\" : \"fresh\");\n    resBadge.className = \"badge \" + (sameRef ? \"same\" : \"fresh\");\n\n    \u002F\u002F Relationship symbol between the two arrays\n    const rel = $(\"rel\");\n    rel.className = \"rel \" + (sameRef ? \"same\" : \"fresh\");\n    $(\"relSym\").textContent = sameRef ? \"===\" : \"!==\";\n    $(\"relCap\").textContent = sameRef ? \"one array\" : \"two arrays\";\n\n    \u002F\u002F Facts\n    $(\"factRef\").innerHTML = sameRef\n      ? '\u003Cspan class=\"t\">true\u003C\u002Fspan>'\n      : '\u003Cspan class=\"f\">false\u003C\u002Fspan>';\n    $(\"factMut\").innerHTML = mutated\n      ? '\u003Cspan class=\"t\">yes\u003C\u002Fspan>'\n      : '\u003Cspan class=\"f\">no\u003C\u002Fspan>';\n\n    \u002F\u002F Re-render light — the payoff\n    const rr = $(\"rerender\");\n    rr.classList.remove(\"pulse\");\n    void rr.offsetWidth; \u002F\u002F restart the flash animation\n    if (reRender) {\n      rr.className = \"rerender fresh pulse\";\n      rr.innerHTML = \"✓ React re-renders — new reference\";\n    } else {\n      rr.className = \"rerender stale pulse\";\n      rr.innerHTML = \"⚠️ React skips the re-render — UI is stale\";\n    }\n\n    \u002F\u002F Plain-English narration\n    $(\"status\").innerHTML = statusFor(op, result, sameRef, i, note);\n\n    $(\"empty\").hidden = true;\n    $(\"resultBody\").hidden = false;\n    refreshWithIdx();\n  }\n\n  function statusFor(op, result, sameRef, i, note) {\n    const oid = idOf(original);\n    if (sameRef) {\n      const verb = { sort: \"sorted\", reverse: \"reversed\", splice: \"spliced\" }[op] || \"changed\";\n      let s =\n        `\u003Ccode>${op}()\u003C\u002Fcode> ${verb} the array \u003Cspan class=\"hot\">in place\u003C\u002Fspan> and returned the ` +\n        `\u003Cspan class=\"hot\">very same array\u003C\u002Fspan> (\u003Ccode>${oid}\u003C\u002Fcode>). ` +\n        `Calling \u003Ccode>setTasks(result)\u003C\u002Fcode> hands React the reference it already had — ` +\n        `\u003Cspan class=\"hot\">it bails out and skips the render\u003C\u002Fspan>. The data changed; the screen won't.`;\n      if (note) s += \"\u003Cbr>\u003Cbr>\" + note;\n      return s;\n    }\n    const rid = idOf(result);\n    const verb = {\n      toSorted: \"a sorted copy\", toReversed: \"a reversed copy\",\n      toSpliced: \"a spliced copy\", with: `a copy with index ${i} replaced`,\n    }[op] || \"a new array\";\n    return (\n      `\u003Ccode>${op}()\u003C\u002Fcode> built \u003Cspan class=\"cool\">${verb}\u003C\u002Fspan> — a ` +\n      `\u003Cspan class=\"cool\">brand-new array\u003C\u002Fspan> (\u003Ccode>${rid}\u003C\u002Fcode>) — and left the original ` +\n      `(\u003Ccode>${oid}\u003C\u002Fcode>) \u003Cspan class=\"cool\">untouched\u003C\u002Fspan>. A new reference means ` +\n      `\u003Ccode>setTasks(result)\u003C\u002Fcode> \u003Cspan class=\"cool\">triggers a re-render\u003C\u002Fspan> with the fresh data.`\n    );\n  }\n\n  \u002F\u002F Wire buttons\n  document.querySelectorAll(\".op\").forEach((btn) => {\n    btn.addEventListener(\"click\", () => run(btn.dataset.op));\n  });\n\n  $(\"reset\").addEventListener(\"click\", () => {\n    original = START();          \u002F\u002F fresh array => fresh identity\n    refreshWithIdx();\n    $(\"resultBody\").hidden = true;\n    $(\"empty\").hidden = false;\n  });",{"height":40,"autorun":17},520,{"slug":33,"title":42,"excerpt":43,"coverUrl":44},"Your `.sort()` is mutating state. JavaScript finally gave you the fix.","The classic array methods — sort, reverse, splice — mutate the original array, silently breaking React state updates and surprising anyone who forgot to spread first. ES2023 added four immutable counterparts: toSorted, toReversed, toSpliced, and with.","\u002Fmedia\u002Fcovers\u002Fimmutable-array-methods.png"]