JavaScript arrays store ordered lists of data in a single variable, accessed by zero-based index. This lesson covers creating and reading arrays, mutating them with push/pop/shift/unshift/splice, copying safely with slice, and iterating with for...of and forEach.
1JavaScript Arrays Part 1
If variables are boxes that hold one thing, arrays are shelves — a single variable that stores an entire ordered list. Every to-do list, every product catalog, every chat thread is an array under the hood.
// One variable → one value
const color = 'Red';
// One array → unlimited ordered values
const colors = ['Red', 'Green', 'Blue', 'Yellow'];
// 0 1 2 3Arrays = Shelves
2JavaScript Arrays Part 2
Create an array with square brackets [ ]. Each value sits in a numbered slot called an INDEX — and counting starts at 0, not 1. This is zero-based indexing.
const fruits = ['Apple', 'Banana', 'Cherry', 'Date'];
// slot: [ 0 ] [ 1 ] [ 2 ] [ 3 ]
console.log(fruits[0]); // 'Apple' ← first item
console.log(fruits[3]); // 'Date' ← last item
console.log(fruits[4]); // undefined ← out of boundsZero-Based Indexing
3JavaScript Arrays Part 3
JavaScript arrays can hold ANY data type — strings, numbers, booleans, objects, and even other arrays. When you put arrays inside arrays, you get multi-dimensional data structures.
// Mixed types in one array
const mix = ['Hello', 42, true, null, { id: 1 }];
// Nested arrays → 2D grid
const grid = [
['X', 'O', 'X'],
['O', 'X', 'O'],
['X', 'O', 'X'],
];
console.log(grid[0][2]); // 'X' (row 0, col 2)
console.log(grid[1][1]); // 'X' (row 1, col 1 — center)2D Grid Structures
4JavaScript Arrays Part 4
Every array tracks its own size with .length. It updates automatically when you add or remove items. The last element is always at index length - 1.
const tasks = ['Design', 'Build', 'Test'];
console.log(tasks.length); // 3
// Dynamic last-item access
console.log(tasks[tasks.length - 1]); // 'Test'
// ES2022 alternative
console.log(tasks.at(-1)); // 'Test'
// Empty array check
if (tasks.length === 0) {
console.log('No tasks!');
}Array .length
5JavaScript Arrays Part 5
Four mutation methods control the ends of an array. push/pop work on the END (like a stack of plates). shift/unshift work on the START (like a queue at a store).
const stack = ['A', 'B', 'C'];
// ── END operations (Stack pattern) ──
stack.push('D'); // Add to end → ['A','B','C','D']
stack.pop(); // Remove end → ['A','B','C']
// ── START operations (Queue pattern) ──
stack.unshift('Z'); // Add to start → ['Z','A','B','C']
stack.shift(); // Remove start → ['A','B','C']Mutation Methods
6JavaScript Arrays Part 6
splice() is the Swiss Army knife: it can INSERT, REMOVE, or REPLACE items at ANY position. It takes: start index, delete count, and items to insert.
const colors = ['Red', 'Green', 'Blue', 'Yellow'];
// REMOVE 1 item at index 1
colors.splice(1, 1);
// → ['Red', 'Blue', 'Yellow']
// INSERT at index 1 without removing
colors.splice(1, 0, 'Purple', 'Pink');
// → ['Red', 'Purple', 'Pink', 'Blue', 'Yellow']
// REPLACE 2 items starting at index 0
colors.splice(0, 2, 'Cyan');
// → ['Cyan', 'Pink', 'Blue', 'Yellow']splice(start, count, ...items)
7JavaScript Arrays Part 7
Two main ways to process every element: for...of extracts values directly (clean, modern), while forEach takes a callback with value AND index (functional style).
const items = ['Pen', 'Paper', 'Ink'];
// ✅ for...of — direct value access
for (const item of items) {
console.log(item); // 'Pen', 'Paper', 'Ink'
}
// ✅ forEach — value + index via callback
items.forEach((item, index) => {
console.log(`${index + 1}. ${item}`);
});
// '1. Pen'
// '2. Paper'
// '3. Ink'Array Iteration
8JavaScript Arrays Part 8
Easily confused: slice() copies a portion WITHOUT changing the original (immutable). splice() modifies the original array in place (mutable). The 'p' in splice means it PERMANENTLY changes.
const letters = ['A', 'B', 'C', 'D', 'E'];
// slice(start, end) — immutable copy
const middle = letters.slice(1, 4);
// middle → ['B', 'C', 'D']
// letters → ['A', 'B', 'C', 'D', 'E'] ← unchanged!
// splice(start, count) — mutates original
const removed = letters.splice(1, 2);
// removed → ['B', 'C']
// letters → ['A', 'D', 'E'] ← modified!slice vs splice
9JavaScript Arrays Part 9
Arrays mastered: creation with [], zero-based indexing, .length for size, push/pop/shift/unshift for mutation, splice for surgical edits, slice for safe copies, and iteration with for...of and forEach. Next: JavaScript Objects.
Array Master
10Step-by-Step Breakdown
If variables are boxes that hold one thing, arrays are shelves — a single variable that stores an entire ordered list. Every to-do list, every product catalog, every chat thread is an array under the hood.
Create an array with square brackets [ ]. Each value sits in a numbered slot called an INDEX — and counting starts at 0, not 1. This is zero-based indexing.
JavaScript arrays can hold ANY data type — strings, numbers, booleans, objects, and even other arrays. When you put arrays inside arrays, you get multi-dimensional data structures.
Checkpoint: What is the index of the FIRST element in a JavaScript array?
- →1
- →0
Every array tracks its own size with .length. It updates automatically when you add or remove items. The last element is always at index length - 1.
Checkpoint: Which property gives you the total number of items in an array?
- →size
- →length
Four mutation methods control the ends of an array. push/pop work on the END (like a stack of plates). shift/unshift work on the START (like a queue at a store).
splice() is the Swiss Army knife: it can INSERT, REMOVE, or REPLACE items at ANY position. It takes: start index, delete count, and items to insert.
Two main ways to process every element: for...of extracts values directly (clean, modern), while forEach takes a callback with value AND index (functional style).
Easily confused: slice() copies a portion WITHOUT changing the original (immutable). splice() modifies the original array in place (mutable). The 'p' in splice means it PERMANENTLY changes.
Checkpoint: If an array has a length of 5, what is the index of the LAST element?
- →5
- →4
Arrays mastered: creation with [], zero-based indexing, .length for size, push/pop/shift/unshift for mutation, splice for surgical edits, slice for safe copies, and iteration with for...of and forEach. Next: JavaScript Objects.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Reflect Array Mutations in the Accessible DOM Immediately
When splice(), push(), or shift() change the array backing a rendered list, the corresponding DOM update (adding/removing/reordering `<li>` elements) must happen in the same render pass — otherwise a screen reader announces a stale item count or reads elements in an order that no longer matches the underlying data.
SEO Implications
- 1
Arrays Populated Only After Client-Side Mutation Can Leave Crawlers with an Empty Page
If a page's content list starts as an empty array and is only filled in via push()/splice() calls triggered by client-side JavaScript after load, a crawler that indexes before those mutations run sees nothing. Pre-populating the array server-side avoids leaving the indexed page blank.
Best Practices
Prefer slice() Over splice() When You Don't Want to Mutate the Original Array
slice(start, end) returns a new array and leaves the source untouched, while splice() mutates the original in place and returns the removed elements. Default to slice() (or the spread operator) unless you specifically intend to change the original array.
Use .at(-1) Instead of array[array.length - 1] for Reading the Last Element
Both work, but .at(-1) (ES2022) is more explicit about intent and also supports negative indices for reading from any position near the end, without needing to compute .length - N yourself.
Frequent Bugs
Confusing slice() and splice() and accidentally mutating an array you meant to only read from.
slice() is non-mutating and returns a copy; splice() mutates the original array and returns the removed items. A helpful mnemonic: the 'p' in splice stands for 'permanent' — it permanently changes the array it's called on.
Assuming array.length - 1 is always safe to use as the last index, even on an empty array.
On an empty array, length is 0, so length - 1 is -1, and array[-1] returns undefined (JavaScript doesn't support negative indices with bracket notation). Always check array.length > 0 before assuming a last element exists.
Real-World Examples
Removing a Single To-Do Item by Index with splice()
A to-do list app needed to let users delete a specific task from the middle of the list without disturbing the order of the remaining tasks or creating a new array reference unnecessarily.
const tasks = ['Design', 'Build', 'Test', 'Deploy'];
// Remove 'Test' (index 2) in place
tasks.splice(2, 1);
console.log(tasks); // ['Design', 'Build', 'Deploy']