Array Mutation Methods: sort() Lies!
10 comes before 2? Yes, in string comparison! And shift() is the slowest array method — know why or get trapped in interviews.
push/pop add and remove from the END of an array. They are O(1) amortized — the fastest array operations you can get.
unshift/shift add and remove from the START. They are O(n) because every element must be re-indexed when the first slot changes.
const arr = [1, 2, 3];
// O(1) - Fast
arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3]
// O(n) - Slow (re-indexes everything)
arr.unshift(0); // [0, 1, 2, 3] - shifts 1,2,3 right
arr.shift(); // [1, 2, 3] - shifts 1,2,3 left
// Performance test
const large = new Array(100000).fill(0);
console.time('push');
large.push(1);
console.timeEnd('push'); // < 0.1ms
console.time('unshift');
large.unshift(1);
console.timeEnd('unshift'); // > 1ms (1000x slower!)sort() WITHOUT a comparator converts elements to STRINGS, then sorts lexicographically. This is the #1 JavaScript sorting bug.
[10, 2, 1].sort() gives [1, 10, 2] because "10" comes before "2" in string order.
// THE LIE - Sort without comparator
const numbers = [10, 2, 30, 1];
numbers.sort();
console.log(numbers); // [1, 10, 2, 30] — WRONG!
// '10' < '2' because '1' comes before '2' in Unicode
// THE FIX - Numeric comparator
const correct = [10, 2, 30, 1];
correct.sort((a, b) => a - b); // Ascending
console.log(correct); // [1, 2, 10, 30] ✅
// Descending
correct.sort((a, b) => b - a);
// String sorting with localeCompare (for non-ASCII)
const words = ['réservé', 'premier', 'Cliché', 'communiqué'];
words.sort((a, b) => a.localeCompare(b));
// ES2023 toSorted — immutable sort
const original = [3, 1, 2];
const sorted = original.toSorted((a, b) => a - b);
console.log(original); // [3, 1, 2] — unchanged ✅
console.log(sorted); // [1, 2, 3]
splice(start, deleteCount, ...items) is the Swiss army knife for array mutation. Can delete, insert, and replace simultaneously.
Returns an array of the deleted elements. Negative start index counts from the end. O(n) operation.
const arr = ['a', 'b', 'c', 'd', 'e'];
// Delete 2 elements starting at index 1
const deleted = arr.splice(1, 2);
console.log(arr); // ['a', 'd', 'e']
console.log(deleted); // ['b', 'c']
// Insert without deleting (deleteCount = 0)
arr.splice(1, 0, 'x', 'y');
console.log(arr); // ['a', 'x', 'y', 'd', 'e']
// Replace (delete and insert in one step)
arr.splice(1, 2, 'B', 'C');
console.log(arr); // ['a', 'B', 'C', 'd', 'e']
// ES2023 toSpliced — immutable version
const original = [1, 2, 3];
const spliced = original.toSpliced(1, 1, 20);
console.log(original); // [1, 2, 3] — unchanged
console.log(spliced); // [1, 20, 3]reverse() mutates array in place. O(n). ES2023: toReversed().
fill(value, start, end) fills range with a value. WARNING: fill({}) fills with the SAME object reference!
copyWithin(target, start, end) copies a sequence within the array. Fast memory move.
// reverse — mutates!
const arr = [1, 2, 3];
arr.reverse();
console.log(arr); // [3, 2, 1]
// ES2023 toReversed
const orig = [1, 2, 3];
const rev = orig.toReversed();
// fill — useful for initialization
const grid = new Array(5).fill(0); // [0, 0, 0, 0, 0]
// THE TRAP: fill with objects
const objects = new Array(3).fill({ x: 0 });
objects[0].x = 1;
console.log(objects); // [{ x: 1 }, { x: 1 }, { x: 1 }] — SAME OBJECT!
// Correct way to fill with unique objects
const unique = Array.from({ length: 3 }, () => ({ x: 0 }));
// copyWithin — fast internal copy
const buf = [1, 2, 3, 4, 5];
buf.copyWithin(0, 3, 5); // Copy indices 3-5 to index 0
console.log(buf); // [4, 5, 3, 4, 5]ES2023 introduces toSorted(), toReversed(), toSpliced(), and with(): Non-mutating alternatives.
with(index, value) replaces an element at an index and returns a new array (replaces arr[i] = val).
const original = [3, 1, 2];
// Old mutating way
const mutated = [...original];
mutated.sort((a, b) => a - b);
// New immutable way
const sorted = original.toSorted((a, b) => a - b);
console.log(sorted); // [1, 2, 3]
// with() — immutable index update
// Old way: arr[1] = 20 (mutates)
// New way:
const updated = original.with(1, 20); // [3, 20, 2]
console.log(original); // [3, 1, 2] — unchanged!
If you are using React, Vue, or any framework that relies on immutability for change detection, the ES2023 methods are a lifesaver. They eliminate the need for awkward spread-copy-then-mutate patterns like
[...arr].sort().Lo kar liya — Key Points:
- ✅ push/pop are O(1) amortized; shift/unshift are O(n) because they must re-index all elements
- ✅ sort() without a comparator converts elements to strings — [10, 2].sort() gives [10, 2] because "10" < "2"
- ✅ Always use sort((a, b) => a - b) for numeric sorting and localeCompare for strings
- ✅ splice() is the Swiss army knife for deleting, inserting, and replacing elements in an array
- ✅ fill() with objects shares the same reference — use Array.from with a mapper for unique objects
- ✅ ES2023 introduces toSorted, toReversed, toSpliced, and with for immutable array operations
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login