Arrays
What are arrays?
Arrays are ordered collections of values. Use an array when you have a list of items and the order matters.
const scores = [95, 87, 92];
const names = ["Alice", "Bob", "Charlie"];
console.log(names[0]); // "Alice"
console.log(scores.length); // 3
Arrays can contain any JavaScript value, including strings, numbers, booleans, objects, and other arrays. In most real code, keep the items similar so the array is easy to reason about.
Why this matters
Arrays are one of the most common data structures in JavaScript. You'll use them for lists of users, search results, shopping cart items, form fields, scores, messages, and many other collections.
Arrays also come with useful methods like map(), filter(), find(), and reduce(). These methods let you process data clearly without writing every loop by hand.
Creating arrays
Array literals
The most common way to create an array is with square brackets:
const empty = [];
const numbers = [1, 2, 3];
const names = ["Alice", "Bob"];
const rows = [[1, 2], [3, 4]];
Prefer this form in beginner code. It is short and clear.
The Array constructor
JavaScript also has an Array constructor:
const values = new Array(1, 2, 3); // [1, 2, 3]
Avoid new Array() unless you have a specific reason. It has surprising behavior when you pass one number:
const items = new Array(3);
console.log(items); // [empty x 3]
console.log(items.length); // 3
new Array(3) creates an array with three empty slots, not [3].
Accessing elements
Arrays are zero-indexed. The first item is at index 0, the second item is at index 1, and so on.
const names = ["Alice", "Bob", "Charlie"];
console.log(names[0]); // "Alice"
console.log(names[1]); // "Bob"
console.log(names[2]); // "Charlie"
console.log(names[3]); // undefined
If you access an index that does not exist, JavaScript returns undefined.
Length
Use .length to get the number of items:
const names = ["Alice", "Bob", "Charlie"];
console.log(names.length); // 3
Last item
Use .at(-1) to get the last item:
const names = ["Alice", "Bob", "Charlie"];
console.log(names.at(-1)); // "Charlie"
You may also see the older pattern:
const last = names[names.length - 1];
console.log(last); // "Charlie"
Mutating vs non-mutating methods
A key array mental model: some methods mutate the original array, while others return a new array.
Mutating methods
Mutating methods change the original array:
const numbers = [1, 2, 3];
numbers.push(4);
console.log(numbers); // [1, 2, 3, 4]
Common mutating methods include:
push()pop()shift()unshift()splice()sort()reverse()
Non-mutating methods
Non-mutating methods return a new value and leave the original array unchanged:
const numbers = [1, 2, 3];
const doubled = numbers.map((number) => number * 2);
console.log(numbers); // [1, 2, 3]
console.log(doubled); // [2, 4, 6]
Common non-mutating methods include:
map()filter()slice()concat()find()includes()
Important: If you want to keep the original array unchanged before using a mutating method, copy it first:
const original = [1, 2, 3];
const reversed = [...original].reverse();
console.log(original); // [1, 2, 3]
console.log(reversed); // [3, 2, 1]
Adding and removing items
Use push() and pop() at the end of an array:
const items = ["a", "b"];
items.push("c");
console.log(items); // ["a", "b", "c"]
const last = items.pop();
console.log(last); // "c"
console.log(items); // ["a", "b"]
Use unshift() and shift() at the beginning:
const items = ["b", "c"];
items.unshift("a");
console.log(items); // ["a", "b", "c"]
const first = items.shift();
console.log(first); // "a"
console.log(items); // ["b", "c"]
These methods mutate the original array.
Finding items
Use includes() when you only need to know whether a value exists:
const names = ["Alice", "Bob", "Charlie"];
console.log(names.includes("Bob")); // true
console.log(names.includes("Dana")); // false
Use find() when you need the first item that matches a condition:
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" }
];
const user = users.find((user) => user.id === 2);
console.log(user); // { id: 2, name: "Bob" }
Use findIndex() when you need the matching item's index:
const names = ["Alice", "Bob", "Charlie"];
const index = names.findIndex((name) => name.startsWith("C"));
console.log(index); // 2
If no item matches, find() returns undefined and findIndex() returns -1:
const names = ["Alice", "Bob", "Charlie"];
console.log(names.find((name) => name === "Dana")); // undefined
console.log(names.findIndex((name) => name === "Dana")); // -1
Slicing and splicing
slice() copies part of an array without changing the original:
const numbers = [1, 2, 3, 4, 5];
const middle = numbers.slice(1, 4);
console.log(middle); // [2, 3, 4]
console.log(numbers); // [1, 2, 3, 4, 5]
splice() changes the original array by removing or inserting items:
const numbers = [1, 2, 3, 4, 5];
numbers.splice(2, 1, 99);
console.log(numbers); // [1, 2, 99, 4, 5]
Rule of thumb: Use slice() when you want a copy. Use splice() only when you intentionally want to mutate the array.
Iterating over arrays
for...of
Use for...of when you want to do something with each item:
const names = ["Alice", "Bob", "Charlie"];
for (const name of names) {
console.log(name);
}
Output:
Alice
Bob
Charlie
Prefer for...of when you do not need the index.
Traditional for loop
Use a traditional for loop when you need the index:
const names = ["Alice", "Bob", "Charlie"];
for (let i = 0; i < names.length; i++) {
console.log(`${i}: ${names[i]}`);
}
Output:
0: Alice
1: Bob
2: Charlie
forEach()
forEach() runs a function for each item:
const names = ["Alice", "Bob", "Charlie"];
names.forEach((name, index) => {
console.log(`${index}: ${name}`);
});
Output:
0: Alice
1: Bob
2: Charlie
Use forEach() for simple side effects, like logging or updating the page. Use map() when you want to create a new array.
Transforming arrays
map()
map() creates a new array by transforming each item:
const numbers = [1, 2, 3, 4];
const doubled = numbers.map((number) => number * 2);
console.log(doubled); // [2, 4, 6, 8]
Use map() when the output array should have one new item for each original item.
filter()
filter() creates a new array with only the items that pass a test:
const numbers = [1, 2, 3, 4, 5, 6];
const evens = numbers.filter((number) => number % 2 === 0);
console.log(evens); // [2, 4, 6]
Use filter() when you want to keep some items and remove others.
reduce()
reduce() combines all items into one value:
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((total, number) => total + number, 0);
console.log(sum); // 10
Use reduce() for totals, grouped objects, and other "combine everything" operations. If reduce() makes the code hard to read, a loop is fine.
Rule of thumb: Include the starting value, like 0 in the example above. It keeps the behavior clear and avoids errors with empty arrays.
Chaining methods
You can chain array methods to process data step by step:
const numbers = [1, 2, 3, 4, 5, 6];
const result = numbers
.filter((number) => number % 2 === 0)
.map((number) => number * number)
.reduce((total, number) => total + number, 0);
console.log(result); // 56
Keep chains short enough to read. If a chain gets confusing, split it into named intermediate variables.
Common patterns
Checking if an array is empty
Empty arrays are truthy, so check .length:
const items = [];
if (items.length === 0) {
console.log("Array is empty");
}
Copying arrays
Use the spread operator for a shallow copy:
const original = [1, 2, 3];
const copy = [...original];
console.log(copy); // [1, 2, 3]
This is a shallow copy. Nested objects and arrays are still shared.
const original = [{ name: "Alice" }];
const copy = [...original];
copy[0].name = "Bob";
console.log(original[0].name); // "Bob"
The array was copied, but the object inside it was still shared.
Rest and spread syntax are covered in more detail in the rest and spread guide.
Combining arrays
Use spread syntax or concat():
const first = [1, 2];
const second = [3, 4];
const combined = [...first, ...second];
console.log(combined); // [1, 2, 3, 4]
Sorting numbers
sort() mutates the original array and sorts values as strings by default. For numbers, pass a compare function:
const numbers = [10, 5, 40, 25];
numbers.sort();
console.log(numbers); // [10, 25, 40, 5]
That result happens because the default sort compares values as strings.
const numbers = [10, 5, 40, 25];
numbers.sort((a, b) => a - b);
console.log(numbers); // [5, 10, 25, 40]
To avoid mutating the original:
const numbers = [10, 5, 40, 25];
const sorted = [...numbers].sort((a, b) => a - b);
console.log(numbers); // [10, 5, 40, 25]
console.log(sorted); // [5, 10, 25, 40]
Checking whether a value is an array
Use Array.isArray() when you need to confirm that a value is an array:
const items = ["a", "b"];
const user = { name: "Alice" };
console.log(Array.isArray(items)); // true
console.log(Array.isArray(user)); // false
Do not use typeof for this check. Arrays are objects, so typeof [] returns "object".
Arrays vs objects
Use arrays when:
- Order matters
- You have a list of similar items
- You want to iterate over every item
- You want array methods like
map(),filter(), andreduce()
Use objects when:
- You need to look up values by name
- The data has meaningful properties
- You are representing one structured thing, like a user or configuration
const names = ["Alice", "Bob", "Charlie"];
const user = {
name: "Alice",
age: 30
};
Best practices
- Prefer array literals: Use
[]instead ofnew Array(). - Use
constfor arrays by default: The array can still be mutated, but the variable cannot be reassigned. - Check
.lengthfor emptiness: Empty arrays are truthy. - Know which methods mutate: Be careful with
sort(),reverse(),splice(), and push/pop methods. - Use
map()for transformation: Do not use it just for side effects. - Keep chains readable: Split long chains into named steps.
- Use
Array.isArray()for array checks:typeofcannot tell arrays and plain objects apart. - Use objects for named data: If each value needs a label, an object may be clearer than an array.
Summary
Arrays are ordered collections for lists of values. Use indexes to access items, .length to check size, and methods like map(), filter(), find(), and reduce() to process data. Remember the mutation rule: some methods change the original array, while others return a new value. When in doubt, choose the method that makes the data flow easiest to read.