Arrays
A contiguous space in memory that holds a list of multiple elements, all stored sequentially.
How Memory Works
When you create an array, the computer reserves a block of memory where each element sits right next to the others. Think of it like a row of boxes:
[11 | 11 | 00 | 00 | 11 | 11 | 00 | 00]
Each cell is a byte. An i32 (32-bit integer) takes 4 bytes, so 2 integers occupy 8 bytes total.
Typed Arrays (Low Level)
At the lowest level, an array is just raw bytes in memory — an ArrayBuffer. How you interpret those bytes depends on the type you use.
// javascript
const a = new ArrayBuffer(8) // 8 bytes of memory, all zeros
const a32 = new Uint32Array(a) // views those 8 bytes as 2 x 32-bit integers
// Uint32Array(2) [ 0, 0 ]
const a8 = new Uint8Array(a) // views those 8 bytes as 8 x 8-bit integers
// Uint8Array(8) [ 0, 0, 0, 0, 0, 0, 0, 0 ]
Both a32 and a8 point to the same memory. Changing one changes the other:
a32[0] = 4294967295 // 0xFFFFFFFF in hex
// a32 → Uint32Array(2) [ 4294967295, 0 ]
// a8 → Uint8Array(8) [ 255, 255, 255, 255, 0, 0, 0, 0 ]
// a → ArrayBuffer { [Uint8Contents]: <ff ff ff ff 00 00 00 00> }
4294967295 in binary is 32 ones (11111111 11111111 11111111 11111111), which is 255 in each of the 4 bytes.
Static Arrays (Fixed Size)
In languages like Rust, arrays have a fixed size defined at creation time:
let my_array: [i32; 4] = [1, 2, 3, 4]
// ^ size is fixed at 4
Memory layout (each i32 = 4 bytes = 32 bits):
[11 11 11 | 11 11 11 | 11 11 11 | 00 00 00]
[0] [1] [2] [3]
Reading — O(1) (Constant Time)
Accessing any element by index is instant, no matter the size of the array:
my_array[0] // Big O: O(1)
The computer calculates the exact memory address: start + (index × byte_size). No searching needed.
Adding Beyond the Limit — O(n) (Linear Time)
Static arrays cannot grow. If you try my_array[4] = 123, it fails because there is no 5th slot — other data may already occupy that memory.
[11 | 11 | 11 | 00] ← your array ends here
[XXXXX] ← memory already taken by something else
The only solution is to create a new, larger array and copy everything over:
let new_array: [i32; 5] = [1, 2, 3, 4, 123]
This is O(n) because you must copy all n existing elements into the new location.
Dynamic Arrays (JavaScript)
JavaScript arrays are not typed or fixed-size — they are actually objects under the hood:
const arr = [10, 20, 30]
// Internally treated as:
const arr = {
"0": 10,
"1": 20,
"2": 30,
length: 3
}
This means JavaScript arrays can hold mixed types:
const arr = [1, 2, "banana", [1, 2, 3]]
JavaScript runtimes implement this differently under the hood: - Node.js → backed by C++ - Bun → backed by Zig
Big O Summary
| Operation | Big O | Why |
|---|---|---|
| Read by index | O(1) | Direct memory address calculation |
| Write by index (within bounds) | O(1) | Direct memory address calculation |
| Add element (static, out of bounds) | O(n) | Must copy all elements to new memory |
Key Takeaways
- An array is a contiguous block of memory.
- Reading is always O(1) — instant access by index.
- Growing a static array is O(n) — requires allocating new memory and copying.
- In JavaScript, arrays are dynamic objects that abstract the memory management for you.
- At the low level, the same bytes can be interpreted differently depending on the type (Uint8, Uint32, etc.).