[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-immutable-array-methods":32,"code:js:true:4os0mi":266,"code:js:true:5v2lav":267,"code:js:true:txgnmj":268,"code:js:true:1rv7eyh":269,"code:js:true:ald5nf":270,"code:js:true:5mp6hg":271,"code:js:true:jjzcyc":272,"code:js:true:137gp2j":273,"code:js:true:1l7oafk":274,"code:js:true:1f8x95p":275,"code:js:true:19plgft":276},[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,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":41,"likeCount":19,"commentCount":19,"author":42,"vertical":47,"topic":48,"tags":51,"_count":63,"playground":65,"body":67,"bodyMd":249,"seo":250,"translationGroupId":253,"thread":254,"assessments":256,"translations":262,"quiz":264},"019fe660-32b6-757d-a975-3860df795f67","immutable-array-methods","Your `.sort()` is mutating state. JavaScript finally gave you the fix.",null,"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",4,"2026-07-15T08:22:28.270Z",28,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},"javascript","JavaScript",[52,54,57,60],{"slug":49,"name":53,"color":36},"Javascript",{"slug":55,"name":56,"color":36},"webdev","Webdev",{"slug":58,"name":59,"color":36},"frontend","Frontend",{"slug":61,"name":62,"color":36},"react","React",{"assessments":64},1,{"slug":34,"title":66},"sort() vs toSorted() — watch the reference",{"blocks":68,"version":64},[69,73,79,82,85,89,92,95,100,103,107,110,113,117,120,123,126,129,132,135,139,142,146,149,153,156,159,163,166,170,173,177,180,183,186,189,193,197,201,204,207,210,213,216,219,222,225,228,231,234,237,240],{"id":70,"html":71,"type":72},"b1","\u003Cp>Here is a bug I have shipped before. Maybe you have too:\u003C\u002Fp>","paragraph",{"id":74,"code":75,"type":76,"language":77,"highlight":78},"b2","const [tasks, setTasks] = useState(initialTasks);\n\nfunction sortByPriority() {\n  const sorted = tasks.sort((a, b) => b.priority - a.priority);\n  setTasks(sorted);\n}","code","js",[],{"id":80,"html":81,"type":72},"b3","\u003Cp>This looks correct. It doesn&#39;t work correctly. \u003Ccode>Array.prototype.sort\u003C\u002Fcode> mutates the array in place and returns the same reference. \u003Ccode>sorted\u003C\u002Fcode> and \u003Ccode>tasks\u003C\u002Fcode> point to the same array. React sees the same reference it had before and skips the re-render. The UI doesn&#39;t update, or it updates inconsistently — it depends on whether anything else triggered a render cycle.\u003C\u002Fp>",{"id":83,"html":84,"type":72},"b4","\u003Cp>The fix you&#39;ve been writing for years:\u003C\u002Fp>",{"id":86,"code":87,"type":76,"language":77,"highlight":88},"b5","const sorted = [...tasks].sort((a, b) => b.priority - a.priority);",[],{"id":90,"html":91,"type":72},"b6","\u003Cp>The defensive spread creates a new array, sort mutates \u003Cem>that\u003C\u002Fem> one, and you get a fresh reference React can track. It works. It&#39;s also cargo-cult boilerplate you have to remember to write, and it&#39;s easy to forget under pressure.\u003C\u002Fp>",{"id":93,"html":94,"type":72},"b7","\u003Cp>ES2023 added four methods that make the spread unnecessary.\u003C\u002Fp>",{"id":96,"html":97,"text":98,"type":99,"level":31},"b8","\u003Ccode>toSorted\u003C\u002Fcode> and \u003Ccode>toReversed\u003C\u002Fcode>","toSorted and toReversed","heading",{"id":101,"html":102,"type":72},"b9","\u003Cp>\u003Ccode>Array.prototype.toSorted\u003C\u002Fcode> is the non-mutating version of \u003Ccode>sort\u003C\u002Fcode>. It returns a new sorted array and leaves the original unchanged:\u003C\u002Fp>",{"id":104,"code":105,"type":76,"language":77,"highlight":106},"b10","const tasks = [\n  { id: 1, priority: 2, title: 'Review PR' },\n  { id: 2, priority: 5, title: 'Fix regression' },\n  { id: 3, priority: 1, title: 'Update docs' },\n];\n\nconst sorted = tasks.toSorted((a, b) => b.priority - a.priority);\n\nconsole.log(sorted[0].title); \u002F\u002F 'Fix regression'\nconsole.log(tasks[0].title);  \u002F\u002F 'Review PR' — untouched",[],{"id":108,"html":109,"type":72},"b11","\u003Cp>The API is identical to \u003Ccode>sort\u003C\u002Fcode>. Any comparator that works with \u003Ccode>sort\u003C\u002Fcode> works with \u003Ccode>toSorted\u003C\u002Fcode>. The only difference is where the result lives.\u003C\u002Fp>",{"id":111,"html":112,"type":72},"b12","\u003Cp>\u003Ccode>toReversed\u003C\u002Fcode> is the same story for \u003Ccode>reverse\u003C\u002Fcode>:\u003C\u002Fp>",{"id":114,"code":115,"type":76,"language":77,"highlight":116},"b13","const steps = ['write test', 'make it pass', 'refactor'];\nconst reversed = steps.toReversed();\n\nconsole.log(reversed); \u002F\u002F ['refactor', 'make it pass', 'write test']\nconsole.log(steps[0]); \u002F\u002F 'write test' — original intact",[],{"id":118,"html":119,"type":72},"b14","\u003Cp>\u003Ccode>Array.prototype.reverse\u003C\u002Fcode> is one of the sneakier mutators because it returns \u003Ccode>this\u003C\u002Fcode> — the same array — making \u003Ccode>const rev = arr.reverse()\u003C\u002Fcode> look like it produced a copy when it didn&#39;t.\u003C\u002Fp>",{"id":121,"html":122,"type":72},"b15","\u003C!-- playground:start -->",{"id":124,"html":125,"text":125,"type":99,"level":31},"b16","🎮 Try it yourself",{"id":127,"html":128,"type":72},"b17","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-07-15-immutable-array-methods\u002Fplayground\u002F\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":130,"html":131,"type":72},"b18","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":133,"html":134,"type":72},"b19","\u003C!-- playground:end -->",{"id":136,"html":137,"text":138,"type":99,"level":31},"b20","\u003Ccode>toSpliced\u003C\u002Fcode>","toSpliced",{"id":140,"html":141,"type":72},"b21","\u003Cp>\u003Ccode>splice\u003C\u002Fcode> is the most powerful mutator in the array API. It inserts, removes, and replaces elements in place and returns the removed items — not the resulting array. \u003Ccode>toSpliced\u003C\u002Fcode> flips that contract: it returns the new array with the changes applied and leaves the original unchanged.\u003C\u002Fp>",{"id":143,"code":144,"type":76,"language":77,"highlight":145},"b22","const items = ['a', 'b', 'c', 'd'];\n\n\u002F\u002F Remove 1 item at index 1, insert 'x' and 'y'\nconst updated = items.toSpliced(1, 1, 'x', 'y');\n\nconsole.log(updated); \u002F\u002F ['a', 'x', 'y', 'c', 'd']\nconsole.log(items);   \u002F\u002F ['a', 'b', 'c', 'd'] — untouched",[],{"id":147,"html":148,"type":72},"b23","\u003Cp>The argument signature mirrors \u003Ccode>splice\u003C\u002Fcode> exactly: \u003Ccode>toSpliced(start, deleteCount, ...items)\u003C\u002Fcode>. For insertions at a specific position, deletions from a slice, or multi-item replacements — it&#39;s the same mental model, no mutation.\u003C\u002Fp>",{"id":150,"html":151,"text":152,"type":99,"level":31},"b24","\u003Ccode>with\u003C\u002Fcode> — replacing one item by index","with — replacing one item by index",{"id":154,"html":155,"type":72},"b25","\u003Cp>This one is new in a different way. There was no mutable counterpart to replace because direct assignment (\u003Ccode>arr[i] = value\u003C\u002Fcode>) already did it. What didn&#39;t exist was a way to replace one item at a specific index \u003Cem>without\u003C\u002Fem> touching the original.\u003C\u002Fp>",{"id":157,"html":158,"type":72},"b26","\u003Cp>The workaround was either \u003Ccode>map\u003C\u002Fcode>:\u003C\u002Fp>",{"id":160,"code":161,"type":76,"language":77,"highlight":162},"b27","const updated = items.map((item, i) => i === targetIndex ? newValue : item);",[],{"id":164,"html":165,"type":72},"b28","\u003Cp>Or spread-and-reassign:\u003C\u002Fp>",{"id":167,"code":168,"type":76,"language":77,"highlight":169},"b29","const updated = [...items.slice(0, i), newValue, ...items.slice(i + 1)];",[],{"id":171,"html":172,"type":72},"b30","\u003Cp>Both communicate the intent poorly. \u003Ccode>with\u003C\u002Fcode> is the named operation:\u003C\u002Fp>",{"id":174,"code":175,"type":76,"language":77,"highlight":176},"b31","const items = ['a', 'b', 'c', 'd'];\nconst updated = items.with(1, 'z');\n\nconsole.log(updated); \u002F\u002F ['a', 'z', 'c', 'd']\nconsole.log(items);   \u002F\u002F ['a', 'b', 'c', 'd']",[],{"id":178,"html":179,"type":72},"b32","\u003Cp>It also supports negative indices — \u003Ccode>items.with(-1, &#39;z&#39;)\u003C\u002Fcode> replaces the last element — matching the same convention as \u003Ccode>Array.prototype.at\u003C\u002Fcode>.\u003C\u002Fp>",{"id":181,"html":182,"text":182,"type":99,"level":31},"b33","Why this matters for React (and Zustand, and Immer, and anything with immutable state)",{"id":184,"html":185,"type":72},"b34","\u003Cp>State in React must be treated as immutable. That rule is not a preference — React uses object identity to detect changes, so mutating an existing array and passing the same reference produces no re-render, regardless of whether the contents changed. The same applies to Vue&#39;s reactivity system, Zustand stores, Redux reducers, and any library that compares references before scheduling an update.\u003C\u002Fp>",{"id":187,"html":188,"type":72},"b35","\u003Cp>The immutable array methods give you the correct default:\u003C\u002Fp>",{"id":190,"code":191,"type":76,"language":77,"highlight":192},"b36","\u002F\u002F Before\nsetTasks(prev => [...prev].sort((a, b) => b.priority - a.priority));\n\n\u002F\u002F After\nsetTasks(prev => prev.toSorted((a, b) => b.priority - a.priority));",[],{"id":194,"code":195,"type":76,"language":77,"highlight":196},"b37","\u002F\u002F Before — delete an item\nsetItems(prev => prev.filter((_, i) => i !== indexToRemove));\n\n\u002F\u002F After — splice idiom\nsetItems(prev => prev.toSpliced(indexToRemove, 1));",[],{"id":198,"code":199,"type":76,"language":77,"highlight":200},"b38","\u002F\u002F Before — update one item\nsetItems(prev => prev.map((item, i) => i === idx ? { ...item, done: true } : item));\n\n\u002F\u002F After\nsetItems(prev => prev.with(idx, { ...prev[idx], done: true }));",[],{"id":202,"html":203,"type":72},"b39","\u003Cp>Less ceremony, clearer intent, and no defensive spread to forget.\u003C\u002Fp>",{"id":205,"html":206,"text":206,"type":99,"level":31},"b40","Browser support",{"id":208,"html":209,"type":72},"b41","\u003Cp>All four methods are \u003Cstrong>Baseline 2023\u003C\u002Fstrong>: Chrome 110, Firefox 115, Safari 16, Node.js 20. That&#39;s roughly every browser released in the last two years. No polyfill needed if your browserslist target is reasonably current; a one-liner shim covers the rest.\u003C\u002Fp>",{"id":211,"html":212,"type":72},"b42","\u003C!-- quiz:start -->",{"id":214,"html":215,"text":215,"type":99,"level":31},"b43","🧠 Test yourself",{"id":217,"html":218,"type":72},"b44","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-07-15-immutable-array-methods\">Take the 6-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":220,"html":221,"type":72},"b45","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":223,"html":224,"type":72},"b46","\u003C!-- quiz:end -->",{"id":226,"html":227,"text":227,"type":99,"level":31},"b47","The takeaway",{"id":229,"html":230,"type":72},"b48","\u003Cp>Search your codebase for \u003Ccode>].sort(\u003C\u002Fcode> and \u003Ccode>[...\u003C\u002Fcode> preceding a sort. Every \u003Ccode>[...arr].sort(fn)\u003C\u002Fcode> can become \u003Ccode>arr.toSorted(fn)\u003C\u002Fcode>. Every \u003Ccode>[...arr].reverse()\u003C\u002Fcode> can become \u003Ccode>arr.toReversed()\u003C\u002Fcode>. Every \u003Ccode>arr.map((item, i) =&gt; i === idx ? … : item)\u003C\u002Fcode> that replaces by index can become \u003Ccode>arr.with(idx, …)\u003C\u002Fcode>.\u003C\u002Fp>",{"id":232,"html":233,"type":72},"b49","\u003Cp>The defensive spread was never the right abstraction — it was a workaround for methods that should have had immutable variants from the start. They do now. Use them.\u003C\u002Fp>",{"id":235,"type":236},"b50","divider",{"id":238,"html":239,"type":72},"b51","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":241,"type":242,"items":243,"ordered":18},"b52","list",[244,245,246,247,248],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>","Here is a bug I have shipped before. Maybe you have too:\n\n```js\nconst [tasks, setTasks] = useState(initialTasks);\n\nfunction sortByPriority() {\n  const sorted = tasks.sort((a, b) => b.priority - a.priority);\n  setTasks(sorted);\n}\n```\n\nThis looks correct. It doesn't work correctly. `Array.prototype.sort` mutates the array in place and returns the same reference. `sorted` and `tasks` point to the same array. React sees the same reference it had before and skips the re-render. The UI doesn't update, or it updates inconsistently — it depends on whether anything else triggered a render cycle.\n\nThe fix you've been writing for years:\n\n```js\nconst sorted = [...tasks].sort((a, b) => b.priority - a.priority);\n```\n\nThe defensive spread creates a new array, sort mutates *that* one, and you get a fresh reference React can track. It works. It's also cargo-cult boilerplate you have to remember to write, and it's easy to forget under pressure.\n\nES2023 added four methods that make the spread unnecessary.\n\n## `toSorted` and `toReversed`\n\n`Array.prototype.toSorted` is the non-mutating version of `sort`. It returns a new sorted array and leaves the original unchanged:\n\n```js\nconst tasks = [\n  { id: 1, priority: 2, title: 'Review PR' },\n  { id: 2, priority: 5, title: 'Fix regression' },\n  { id: 3, priority: 1, title: 'Update docs' },\n];\n\nconst sorted = tasks.toSorted((a, b) => b.priority - a.priority);\n\nconsole.log(sorted[0].title); \u002F\u002F 'Fix regression'\nconsole.log(tasks[0].title);  \u002F\u002F 'Review PR' — untouched\n```\n\nThe API is identical to `sort`. Any comparator that works with `sort` works with `toSorted`. The only difference is where the result lives.\n\n`toReversed` is the same story for `reverse`:\n\n```js\nconst steps = ['write test', 'make it pass', 'refactor'];\nconst reversed = steps.toReversed();\n\nconsole.log(reversed); \u002F\u002F ['refactor', 'make it pass', 'write test']\nconsole.log(steps[0]); \u002F\u002F 'write test' — original intact\n```\n\n`Array.prototype.reverse` is one of the sneakier mutators because it returns `this` — the same array — making `const rev = arr.reverse()` look like it produced a copy when it didn't.\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-07-15-immutable-array-methods\u002Fplayground\u002F)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n## `toSpliced`\n\n`splice` is the most powerful mutator in the array API. It inserts, removes, and replaces elements in place and returns the removed items — not the resulting array. `toSpliced` flips that contract: it returns the new array with the changes applied and leaves the original unchanged.\n\n```js\nconst items = ['a', 'b', 'c', 'd'];\n\n\u002F\u002F Remove 1 item at index 1, insert 'x' and 'y'\nconst updated = items.toSpliced(1, 1, 'x', 'y');\n\nconsole.log(updated); \u002F\u002F ['a', 'x', 'y', 'c', 'd']\nconsole.log(items);   \u002F\u002F ['a', 'b', 'c', 'd'] — untouched\n```\n\nThe argument signature mirrors `splice` exactly: `toSpliced(start, deleteCount, ...items)`. For insertions at a specific position, deletions from a slice, or multi-item replacements — it's the same mental model, no mutation.\n\n## `with` — replacing one item by index\n\nThis one is new in a different way. There was no mutable counterpart to replace because direct assignment (`arr[i] = value`) already did it. What didn't exist was a way to replace one item at a specific index *without* touching the original.\n\nThe workaround was either `map`:\n\n```js\nconst updated = items.map((item, i) => i === targetIndex ? newValue : item);\n```\n\nOr spread-and-reassign:\n\n```js\nconst updated = [...items.slice(0, i), newValue, ...items.slice(i + 1)];\n```\n\nBoth communicate the intent poorly. `with` is the named operation:\n\n```js\nconst items = ['a', 'b', 'c', 'd'];\nconst updated = items.with(1, 'z');\n\nconsole.log(updated); \u002F\u002F ['a', 'z', 'c', 'd']\nconsole.log(items);   \u002F\u002F ['a', 'b', 'c', 'd']\n```\n\nIt also supports negative indices — `items.with(-1, 'z')` replaces the last element — matching the same convention as `Array.prototype.at`.\n\n## Why this matters for React (and Zustand, and Immer, and anything with immutable state)\n\nState in React must be treated as immutable. That rule is not a preference — React uses object identity to detect changes, so mutating an existing array and passing the same reference produces no re-render, regardless of whether the contents changed. The same applies to Vue's reactivity system, Zustand stores, Redux reducers, and any library that compares references before scheduling an update.\n\nThe immutable array methods give you the correct default:\n\n```js\n\u002F\u002F Before\nsetTasks(prev => [...prev].sort((a, b) => b.priority - a.priority));\n\n\u002F\u002F After\nsetTasks(prev => prev.toSorted((a, b) => b.priority - a.priority));\n```\n\n```js\n\u002F\u002F Before — delete an item\nsetItems(prev => prev.filter((_, i) => i !== indexToRemove));\n\n\u002F\u002F After — splice idiom\nsetItems(prev => prev.toSpliced(indexToRemove, 1));\n```\n\n```js\n\u002F\u002F Before — update one item\nsetItems(prev => prev.map((item, i) => i === idx ? { ...item, done: true } : item));\n\n\u002F\u002F After\nsetItems(prev => prev.with(idx, { ...prev[idx], done: true }));\n```\n\nLess ceremony, clearer intent, and no defensive spread to forget.\n\n## Browser support\n\nAll four methods are **Baseline 2023**: Chrome 110, Firefox 115, Safari 16, Node.js 20. That's roughly every browser released in the last two years. No polyfill needed if your browserslist target is reasonably current; a one-liner shim covers the rest.\n\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 6-question quiz →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-07-15-immutable-array-methods)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n## The takeaway\n\nSearch your codebase for `].sort(` and `[...` preceding a sort. Every `[...arr].sort(fn)` can become `arr.toSorted(fn)`. Every `[...arr].reverse()` can become `arr.toReversed()`. Every `arr.map((item, i) => i === idx ? … : item)` that replaces by index can become `arr.with(idx, …)`.\n\nThe defensive spread was never the right abstraction — it was a workaround for methods that should have had immutable variants from the start. They do now. Use them.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":35,"canonical":251,"description":252},"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fimmutable-array-methods","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 ","019fe660-32b6-757d-a975-3dbc859ae57c",{"id":255,"locked":18},"019fe660-3967-7261-877e-7f47ab0bd4c3",[257],{"id":258,"slug":34,"title":259,"_count":260},"019fe776-4d12-75fc-b42d-9375ffd5fe8c","Immutable array methods: toSorted, toReversed, toSpliced, with",{"questions":261},6,[263],{"locale":13,"slug":34},{"id":258,"slug":34,"title":259,"_count":265,"questionCount":261},{"questions":261},"\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>tasks\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> setTasks\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-func\">useState\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>initialTasks\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-func\">sortByPriority\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> sorted \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> tasks\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">sort\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>a\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> b\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-func\">setTasks\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>sorted\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-oneline\" data-lang=\"js\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> sorted \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>tasks\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">sort\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>a\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> b\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> tasks \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> id\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> priority\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> title\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'Review PR'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> id\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> priority\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">5\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> title\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'Fix regression'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> id\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> priority\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> title\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'Update docs'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> sorted \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> tasks\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">toSorted\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>a\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> b\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nconsole\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>sorted\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>title\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F 'Fix regression'\n\u003C\u002Fspan>console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>tasks\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>title\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;  \u003Cspan class=\"shj-cmnt\">\u002F\u002F 'Review PR' — untouched\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> steps \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'write test'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'make it pass'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'refactor'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> reversed \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> steps\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">toReversed\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nconsole\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>reversed\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F ['refactor', 'make it pass', 'write test']\n\u003C\u002Fspan>console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>steps\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F 'write test' — original intact\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> items \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'a'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'b'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'c'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'d'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F Remove 1 item at index 1, insert 'x' and 'y'\n\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> updated \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> items\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">toSpliced\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'x'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'y'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nconsole\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>updated\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F ['a', 'x', 'y', 'c', 'd']\n\u003C\u002Fspan>console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>items\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F ['a', 'b', 'c', 'd'] — untouched\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-oneline\" data-lang=\"js\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> updated \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> items\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">map\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>item\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> i\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> i \u003Cspan class=\"shj-oper\">===\u003C\u002Fspan> targetIndex \u003Cspan class=\"shj-oper\">?\u003C\u002Fspan> newValue \u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> item\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-oneline\" data-lang=\"js\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> updated \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>items\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">slice\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> i\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> newValue\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>items\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">slice\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>i \u003Cspan class=\"shj-oper\">+\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> items \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'a'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'b'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'c'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'d'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> updated \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> items\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">with\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'z'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nconsole\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>updated\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F ['a', 'z', 'c', 'd']\n\u003C\u002Fspan>console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>items\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F ['a', 'b', 'c', 'd']\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F Before\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">setTasks\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>prev \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>prev\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">sort\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>a\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> b\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F After\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">setTasks\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>prev \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> prev\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">toSorted\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>a\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> b\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> b\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> a\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>priority\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F Before — delete an item\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">setItems\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>prev \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> prev\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">filter\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>_\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> i\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> i \u003Cspan class=\"shj-oper\">!==\u003C\u002Fspan> indexToRemove\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F After — splice idiom\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">setItems\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>prev \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> prev\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">toSpliced\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>indexToRemove\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-cmnt\">\u002F\u002F Before — update one item\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">setItems\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>prev \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> prev\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">map\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>item\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> i\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> i \u003Cspan class=\"shj-oper\">===\u003C\u002Fspan> idx \u003Cspan class=\"shj-oper\">?\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>item\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> done\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> item\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F After\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">setItems\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>prev \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> prev\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">with\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>idx\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">...\u003C\u002Fspan>prev\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>idx\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> done\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-bool\">true\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]