What you'll learn
- Quick answer
- Two Kinds of Array Methods: Mutating vs Non-Mutating
- push, pop, shift & unshift: Add and Remove at the Ends
- slice vs splice: Copy or Cut (the Big Gotcha)
- indexOf, includes & find: Searching an Array
- sort: Ordering an Array (and Why Numbers Look Wrong)
- Which Methods Mutate? A Quick Reference
- When to Use Which — and How to Practise
- FAQ
Quick Answer
JavaScript array methods fall into two groups: some change (mutate) the original array, and some return a new value and leave it alone. push, pop, shift, unshift, splice and sort mutate the array, while slice, indexOf, includes and find do not. Learn which is which and you avoid a whole class of confusing bugs. This guide gives a one-line example and a clear use case for each.
Two Kinds of Array Methods: Mutating vs Non-Mutating
When people talk about javascript array methods, they usually jump straight to map, filter and reduce. Those are great, but they are only part of the toolkit. Long before you reach them, you will reach for the everyday methods that add items, remove items, copy a slice, search for a value, or sort a list. This guide tours ten of those workhorse methods, with a one-line example and a clear use case for each.
The single most useful idea to hold in your head is this: array methods come in two flavours.
- Mutating methods change the original array in place. After you call them, the array is different.
- Non-mutating methods leave the original alone and hand you back a new value — a copy, an index, a boolean, or an item.
Mixing these up is one of the most common sources of "why did my data change?!" bugs for beginners. We will flag which group each method belongs to as we go, and there is a full table near the end. If you want the complete, ordered path through arrays and the rest of the language, our free JavaScript course covers all of this from scratch.
push, pop, shift & unshift: Add and Remove at the Ends
These four methods work at the two ends of an array. All four mutate the original.
push — add to the end
const fruits = ["apple", "banana"];
fruits.push("cherry");
console.log(fruits); // ["apple", "banana", "cherry"]push tacks one or more items onto the end and returns the array's new length. Use it whenever you are building a list up item by item.
pop — remove from the end
const nums = [1, 2, 3];
const last = nums.pop();
console.log(last); // 3
console.log(nums); // [1, 2]pop removes the last item and returns it. Together, push and pop turn an array into a stack — last in, first out.
unshift — add to the front
const nums = [2, 3];
nums.unshift(1);
console.log(nums); // [1, 2, 3]unshift adds items to the start and returns the new length.
shift — remove from the front
const queue = ["a", "b", "c"];
const first = queue.shift();
console.log(first); // "a"
console.log(queue); // ["b", "c"]shift removes the first item and returns it, so push plus shift gives you a queue — first in, first out. One gotcha: shift and unshift have to renumber every remaining item, so on very large arrays they are slower than push and pop at the end.
slice vs splice: Copy or Cut (the Big Gotcha)
These two names look almost identical, which is exactly why beginners confuse them. The difference matters a lot.
slice — copy part of an array (does NOT mutate)
const letters = ["a", "b", "c", "d", "e"];
const middle = letters.slice(1, 3);
console.log(middle); // ["b", "c"]
console.log(letters); // ["a", "b", "c", "d", "e"] — unchangedslice(start, end) returns a shallow copy of the items from start up to but not including end. The original array is untouched. A handy trick: arr.slice() with no arguments makes a quick copy of the whole array.
splice — cut, insert, or replace (MUTATES)
const colors = ["red", "green", "blue"];
const removed = colors.splice(1, 1);
console.log(removed); // ["green"]
console.log(colors); // ["red", "blue"]splice(start, deleteCount, ...itemsToInsert) changes the array in place and returns an array of whatever it removed. You can also insert without deleting by passing 0 as the delete count:
const colors = ["red", "blue"];
colors.splice(1, 0, "green"); // insert at index 1, delete nothing
console.log(colors); // ["red", "green", "blue"]Remember: slice copies and is safe; splice changes and mutates. When in doubt and you do not want to touch the original, reach for slice.
indexOf, includes & find: Searching an Array
These three methods look inside an array without changing it. None of them mutate.
indexOf — find the position of a value
const pets = ["cat", "dog", "fish"];
console.log(pets.indexOf("dog")); // 1
console.log(pets.indexOf("bird")); // -1indexOf returns the first index where the value is found, or -1 if it is not there. It compares with strict equality (===), so it is perfect for strings and numbers but will not match objects by their contents.
includes — a simple yes/no check
const pets = ["cat", "dog", "fish"];
console.log(pets.includes("dog")); // trueIf you only care whether a value is present, includes is clearer than writing indexOf(x) !== -1. It returns a plain true or false. Bonus: includes can find NaN in an array, while indexOf cannot.
find — search by a condition
const users = [
{ name: "Aarav", age: 20 },
{ name: "Diya", age: 17 }
];
const minor = users.find((u) => u.age < 18);
console.log(minor); // { name: "Diya", age: 17 }When you are searching a list of objects, or matching on a rule rather than an exact value, find is the tool. It runs your callback on each item and returns the first one that makes it return true, or undefined if nothing matches. A close cousin, findIndex, returns the position instead of the item.
sort: Ordering an Array (and Why Numbers Look Wrong)
sort reorders an array in place, so it mutates the original. It is also the method with the most famous surprise in all of JavaScript.
The gotcha: numbers sort as text by default
const nums = [10, 1, 21, 2];
nums.sort();
console.log(nums); // [1, 10, 2, 21] — not what you expected!With no arguments, sort converts each item to a string and orders them alphabetically. That is why "10" comes before "2" — it compares character by character, and "1" comes before "2".
The fix: pass a compare function
const nums = [10, 1, 21, 2];
nums.sort((a, b) => a - b);
console.log(nums); // [1, 2, 10, 21]The compare function (a, b) => a - b sorts numbers in ascending order; swap it to b - a for descending. For plain strings, the default alphabetical sort is usually fine.
Because sort mutates, make a copy first if you need to keep the original order: const sorted = [...nums].sort((a, b) => a - b);. Newer JavaScript also has toSorted(), which returns a sorted copy and never touches the original.
Which Methods Mutate? A Quick Reference
Here is the one table worth bookmarking. "Mutates" means the method changes the array you call it on.
| Method | What it does | Mutates the original? | Returns |
|---|---|---|---|
| push | Add to the end | Yes | New length |
| pop | Remove from the end | Yes | Removed item |
| unshift | Add to the front | Yes | New length |
| shift | Remove from the front | Yes | Removed item |
| splice | Cut / insert / replace | Yes | Removed items |
| sort | Reorder in place | Yes | The same array |
| slice | Copy part of the array | No | New array |
| indexOf | Find a value's position | No | Index or -1 |
| includes | Check if a value exists | No | true / false |
| find | Get first match by rule | No | Item or undefined |
A quick memory aid: the methods that add or remove items (push, pop, shift, unshift, splice) plus sort all mutate. The methods that read or copy (slice, indexOf, includes, find) do not.
When to Use Which — and How to Practise
You do not need to memorise all ten at once. Pick the right tool by asking what you actually want to do:
- Add or remove at an end? Use
push/popat the end orunshift/shiftat the front. - Take a copy of a section? Use
slice— it is the safe one. - Insert or delete in the middle? Use
splice, and remember it changes the original. - Check if something is there? Use
includesfor yes/no,indexOfwhen you need the position. - Search objects by a rule? Use
find. - Order a list? Use
sort, and pass(a, b) => a - bfor numbers.
The one recommendation that will save you the most debugging time: be deliberate about mutation. In modern codebases — especially with frameworks like React — accidental mutation is a classic bug. When you are unsure, prefer the non-mutating option (slice over splice, a spread copy before sort) so your original data stays predictable.
The fastest way to lock this in is to open your browser console and retype every example above, changing the values to see what happens. When you are ready for the full picture — objects, loops, async code, and real projects — our free, beginner-friendly JavaScript course takes you there step by step.
Frequently Asked Questions
Which JavaScript array methods change the original array?
push, pop, shift, unshift, splice and sort all mutate the array in place. slice, indexOf, includes and find do not — they return a new value and leave the original untouched. When you want to avoid changing your data, prefer the non-mutating options.
What is the difference between slice and splice?
slice returns a shallow copy of part of the array and does not change the original, while splice cuts, inserts or replaces items in place and does mutate it. A simple reminder: slice copies, splice changes.
Why does sort put 10 before 2?
By default sort converts every item to a string and orders them alphabetically, so "10" comes before "2". To sort numbers correctly, pass a compare function: arr.sort((a, b) => a - b) for ascending order.
When should I use find instead of indexOf or includes?
Use find when you are searching by a condition or looking through objects, because it takes a callback and returns the first matching item. Use indexOf or includes when you are checking for an exact value like a string or number.
What is the difference between includes and indexOf?
Both check whether a value is in an array. includes returns a simple true or false, which reads more clearly, while indexOf returns the value's position or -1 if it is missing. Use includes for a yes/no check and indexOf when you need the index. One extra difference: includes can detect NaN, but indexOf cannot.
How do I sort an array without changing the original?
Make a copy first, then sort the copy: const sorted = [...original].sort((a, b) => a - b). Newer JavaScript also offers toSorted(), which returns a sorted copy and leaves the original array as it was.
