Foundations
Arrays
The default choice for ordered data: constant-time index access, linear-time search.
How It Works
An array is a contiguous block of memory that stores elements in order, each one addressable by an integer index. Because the elements sit next to each other in memory and are (conceptually) the same size, the runtime can calculate the exact memory address of any element from its index using simple arithmetic. That's why arr[i] is O(1): no searching required, just a direct address calculation.
In JavaScript, arrays are actually a bit more flexible than the classic fixed-size array from lower-level languages: they can grow, shrink, and hold mixed types. Under the hood, V8 tries to keep arrays "packed" and same-typed for performance, but conceptually you should still reason about them as index-addressable, ordered collections.
Core operations and their complexity:
- Access by index (
arr[i]): O(1). Direct address calculation. - Search by value (
arr.includes(x),indexOf): O(n). You must scan until you find a match. - Push/pop at the end: O(1) amortized. No shifting required.
- Insert/remove at the start or middle (
unshift,splice): O(n). Every subsequent element has to shift to close or open the gap. - Iteration: O(n). Visiting every element once.
Arrays are the right choice when order matters, when you need fast random access by position, or when you're building up a sequence you'll process linearly (two pointers, sliding window, sorting, prefix sums).
// Basic array operations
const scores = [10, 20, 30];
// O(1) access
console.log(scores[1]); // 20
// O(1) amortized append
scores.push(40); // [10, 20, 30, 40]
// O(n) removal from the front: everything shifts left
scores.shift(); // [20, 30, 40]
// O(n) search
const hasThirty = scores.includes(30); // true
// Common interview pattern: two pointers
function reverseInPlace(arr) {
let left = 0;
let right = arr.length - 1;
while (left < right) {
[arr[left], arr[right]] = [arr[right], arr[left]];
left++;
right--;
}
return arr;
}
reverseInPlace(scores); // [40, 30, 20]
Common Mistakes
- Off-by-one errors: using
<=instead of<when looping toarr.length, or mixing uparr.length - 1as the last valid index. - Mutating while iterating: calling
spliceinside afor...ofloop shifts indices out from under you and silently skips elements. - Treating
unshift/spliceat the front as free: these are O(n), not O(1), and can quietly turn an otherwise O(n) algorithm into O(n²) inside a loop. - Forgetting arrays are reference types: passing an array into a function and mutating it affects the caller's copy too, which can cause subtle bugs if not intended.
- Using
==for array/object comparisons:[1,2] === [1,2]isfalse; arrays compare by reference, not value.
Pattern Summary
Reach for an array whenever order and positional access matter; it's the backbone of two-pointer, sliding-window, prefix-sum, and sorting-based problems. The edge it gives you in interviews is O(1) index access combined with predictable, cache-friendly iteration, which is exactly what most "process a sequence" problems are built on.
Advertisement