I’m sure somebody has written about this, but I couldn’t find anything so I’ll share with you what I know.

This is an issue that has endlessly tripped me up in JavaScript and I hope this post will help clarify things a bit and hopefully discover a pattern one can use to discern between mutative and non-mutative array methods.

First, let me define what I mean when I say mutative:

// If a method is mutative, that means it changes the original array.
var foo = [1, 2, 3];
foo.reverse();
console.log(foo); // [3, 2, 1]

// Notice how we didn't assign foo to new variable, reverse() acted upon it in place.
// In contrast, non-mutative array methods return a new copy of the original array.

// Here, the new array concat() generates is lost since we didn't assign it
var bar = [1, 2, 3];
bar.concat([4, 5]); 
console.log(bar); // [1, 2, 3]

// Now if we assign it, bar becomes the new array.
bar = bar.concat([4, 5]);
console.log(bar); // [1, 2, 3, 4, 5]
Mutative Non-Mutative
splice slice
shift, pop concat
unshift, push every *
reverse filter *
sort forEach *
indexOf
lastIndexOf
join
map *
reduce *
reduceRight *
some *
toLocaleString
toString

NB: the functional methods marked with a * can be mutative if the function you pass to them modifies the original array. In my expierience this has been especially true in the case of Array.prototype.forEach.

Tips for telling which Array.prototype methods are mutative

  • Just glancing at this list, we can see that an even 1/3 of array methods are mutative, so you can assume most array methods are non-mutative.
  • All functional methods (marked with a *) are non-mutative.
  • All operations modifying the beginning and end of an array are mutative (push, pop, shift, unshift).
  • The only other mutative array methods are splice, reverse, and sort. If you can remember those three and the above rules, telling array methods apart should become a lot easier.