{
    "slug": "js_array_tosorted",
    "term": "toSorted / toReversed / with — Immutable Array Methods",
    "category": "javascript",
    "difficulty": "beginner",
    "short": "JavaScript ES2023 adds immutable counterparts to mutating array methods: toSorted() returns a sorted copy, toReversed() returns a reversed copy, and with(index, value) returns a copy with one element replaced — none mutate the original array.",
    "long": "JavaScript's sort(), reverse(), and direct index assignment mutate arrays in place — a common source of bugs when arrays are shared across components or passed to functions. ES2023 standardises immutable alternatives: Array.prototype.toSorted() returns a new sorted array without touching the original. Array.prototype.toReversed() returns a new reversed array. Array.prototype.with(index, value) returns a copy with the element at index replaced with value — equivalent to the spread pattern '[...arr.slice(0, i), value, ...arr.slice(i+1)]' but readable. Array.prototype.toSpliced() is the immutable splice(). These also work on TypedArrays.",
    "aliases": [
        "toSorted",
        "toReversed",
        "Array.with",
        "immutable array methods",
        "ES2023 arrays"
    ],
    "tags": [
        "javascript",
        "arrays",
        "immutability",
        "es2023"
    ],
    "misconception": "toSorted() is slower because it copies the array. The copy overhead is O(n) — the same cost you pay manually with [...arr].sort(). The clarity and safety benefit is free.",
    "why_it_matters": "Accidental mutation of a shared array is one of the most common JS bugs — sort() on a React state array mutates it before the re-render, causing unpredictable behaviour. toSorted() makes immutability the default for these operations. The with() method is particularly valuable in state management: updating one item in an array without spread syntax.",
    "common_mistakes": [
        "Using toSorted() in environments that don't support ES2023 — check browser compatibility or add a polyfill; Node.js 20+ supports all four methods.",
        "Confusing with() with a setter — arr.with(2, 99) returns a new array; arr[2] = 99 mutates in place. They are not interchangeable.",
        "Not using toSorted() in React or similar frameworks where prop mutation causes silent bugs — this is the primary use case for these methods.",
        "Forgetting toSpliced() — toSorted, toReversed, and with() are well-known, but toSpliced() (immutable splice) is less remembered and equally useful."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "js_array_methods",
        "js_object_mutation_bugs",
        "js_spread_rest",
        "js_structuredclone"
    ],
    "prerequisites": [],
    "refs": [
        "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toSorted"
    ],
    "bad_code": "// ❌ sort() mutates the original — React state bug\nfunction ProductList({ products }) {\n    const sorted = products.sort((a, b) => a.price - b.price);\n    // products (the prop) is now mutated!\n    // Parent component's state changed without a setState call\n    return sorted.map(p => <Product key={p.id} {...p} />);\n}\n\n// ❌ Verbose immutable update\nconst updated = [\n    ...items.slice(0, index),\n    newItem,\n    ...items.slice(index + 1),\n];",
    "good_code": "// ✅ toSorted() — original unchanged\nfunction ProductList({ products }) {\n    const sorted = products.toSorted((a, b) => a.price - b.price);\n    // products is untouched\n    return sorted.map(p => <Product key={p.id} {...p} />);\n}\n\n// ✅ with() — readable single-item update\nconst updated = items.with(index, newItem);\n\n// ✅ Full set of ES2023 immutable methods\nconst arr = [3, 1, 4, 1, 5];\nconst sorted   = arr.toSorted();          // [1, 1, 3, 4, 5]\nconst reversed = arr.toReversed();        // [5, 1, 4, 1, 3]\nconst replaced = arr.with(2, 99);         // [3, 1, 99, 1, 5]\nconst spliced  = arr.toSpliced(1, 2, 9); // [3, 9, 1, 5]\n// arr is still [3, 1, 4, 1, 5] throughout",
    "quick_fix": "Replace arr.sort(fn) with arr.toSorted(fn) and arr.reverse() with arr.toReversed() when you do not intend to mutate the original. Replace [...arr.slice(0,i), v, ...arr.slice(i+1)] with arr.with(i, v).",
    "effort": "low",
    "created": "2026-03-23",
    "updated": "2026-04-05",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/js_array_tosorted",
        "html_url": "https://codeclaritylab.com/glossary/js_array_tosorted",
        "json_url": "https://codeclaritylab.com/glossary/js_array_tosorted.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[toSorted / toReversed / with — Immutable Array Methods](https://codeclaritylab.com/glossary/js_array_tosorted) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/js_array_tosorted"
            }
        }
    }
}