Array Mutator to Accessor Converter
Convert JavaScript array mutator methods (push, splice, sort, reverse, pop, shift, unshift) to immutable accessor equivalents instantly.
About
JavaScript array mutator methods (push, pop, splice, sort, reverse, shift, unshift) modify the original array in place. This is the single largest source of state-mutation bugs in front-end applications. A stale reference to a mutated array propagates through React state, Redux reducers, or any shared-memory context and produces rendering artifacts that are extremely difficult to trace. This tool rewrites mutator calls into their immutable accessor equivalents using spread syntax, slice, concat, and filter. The output preserves the original semantics while guaranteeing the source array remains untouched. It handles assignment contexts, standalone calls, chained expressions, and the return-value difference between mutators that return lengths versus mutators that return elements.
Limitations: this converter operates on surface-level pattern matching, not a full AST. Deeply nested or dynamically computed method names (e.g., arr[method]()) will not be detected. Minified or obfuscated code may produce incorrect results. For production refactoring of large codebases, pair this with ESLint rules like no-array-mutation. Pro tip: after conversion, verify that downstream code does not rely on the mutator's return value (e.g., push returns the new length, not the new array).
Formulas
Each mutator method follows a deterministic rewrite rule. The converter applies pattern matching against the general form:
The transformation rules are:
Where arr is any valid JavaScript identifier or member expression, s is the start index, d is the delete count, and items are the replacement elements. The converter preserves whitespace and indentation context. For splice with no delete count argument, the converter defaults d = 0. For assignment contexts (e.g., const result = arr.push(x)), the converter wraps the immutable expression into the assignment target.
Reference Data
| Mutator Method | Mutates Original | Return Value | Immutable Equivalent | Equivalent Return Value | Notes |
|---|---|---|---|---|---|
| push(...items) | Yes | New length | [...arr, ...items] | New array | Return value type changes from number to Array |
| pop() | Yes | Removed element | arr.slice(0, −1) | New array (without last) | Original returns the popped element, not the array |
| shift() | Yes | Removed element | arr.slice(1) | New array (without first) | Original returns the shifted element, not the array |
| unshift(...items) | Yes | New length | [...items, ...arr] | New array | Return value type changes from number to Array |
| splice(start, del, ...items) | Yes | Array of removed elements | [...arr.slice(0, start), ...items, ...arr.slice(start + del)] | New array | Most complex transformation; original returns removed items |
| sort(fn) | Yes | Sorted array (same ref) | [...arr].sort(fn) | New sorted array | Spread-then-sort creates a shallow copy first |
| reverse() | Yes | Reversed array (same ref) | [...arr].reverse() | New reversed array | Spread-then-reverse creates a shallow copy first |
| fill(val, start, end) | Yes | Modified array (same ref) | [...arr].fill(val, start, end) | New filled array | ES6 mutator, often overlooked |
| copyWithin(t, s, e) | Yes | Modified array (same ref) | [...arr].copyWithin(t, s, e) | New array | Rarely used but still a mutator |
| map(fn) | No | New array | Already immutable | New array | Accessor - no conversion needed |
| filter(fn) | No | New array | Already immutable | New array | Accessor - no conversion needed |
| slice(s, e) | No | New array | Already immutable | New array | Accessor - no conversion needed |
| concat(...items) | No | New array | Already immutable | New array | Accessor - no conversion needed |
| reduce(fn, init) | No | Accumulated value | Already immutable | Accumulated value | Accessor - no conversion needed |
| indexOf(val) | No | Index number | Already immutable | Index number | Accessor - no conversion needed |