Arrays & Typed Arrays
|
This section documents modern ECMAScript and core browser JavaScript APIs — it is not tied to any specific framework or library (React, Vue, Angular, etc.). This content was generated with the assistance of AI and should be verified against the current ECMAScript specification and MDN documentation before relying on it in production, since JavaScript language features and browser API support continue to evolve. This section’s bibliography lists the reference material consulted while preparing these pages. |
Arrays are JavaScript’s ordered, integer-indexed collections. This page covers how to create and read them, their quirks (sparseness, array-likeness), the standard library of array methods every day-to-day script leans on, and typed arrays — the fixed-size, binary-backed cousin of the regular array used for raw numeric data.
Array Literals and Creation
The array literal — a comma-separated list inside square brackets — is how almost every array in modern code comes into existence:
let empty = [];
let primes = [2, 3, 5, 7, 11];
let mixed = [1, "two", [3, 3], { four: 4 }]; // elements can be any type, including other arrays/objects
let sparse = [1, , 3]; // a "hole" at index 1 -- see "Sparse Arrays" below
A trailing comma after the last element is allowed and ignored; it makes future diffs cleaner when adding a new
element. Two elements separated by two commas ([1, , 3]) create a sparse array, discussed below.
Arrays can also be spread into a new array literal with the … spread syntax, which copies each element of an
iterable into the new array:
let a = [1, 2, 3];
let b = [0, ...a, 4]; // [0, 1, 2, 3, 4]
let letters = [..."abc"]; // ['a', 'b', 'c'] -- strings are iterable too
let clone = [...a]; // a shallow copy of a
Beyond the literal, Array() (rarely used directly — Array(5) creates a sparse array of length 5, which
surprises most developers the first time they hit it), Array.of(…values) (creates an array from its
arguments, sidestepping the Array(n) special case), and Array.from(iterableOrArrayLike, mapFn?) (converts an
iterable or array-like object — see "Array-Like Objects" below — into a real array, optionally mapping each
element) round out the ways to construct one:
Array.of(7); // [7] (not an array of length 7)
Array.from("hello"); // ['h', 'e', 'l', 'l', 'o']
Array.from({ length: 3 }, (_, i) => i * 2); // [0, 2, 4]
Reading and Writing Elements
Elements are accessed with square-bracket notation, using a non-negative integer index (arrays are, under the hood, ordinary objects whose property names happen to be stringified integers):
let a = ["zero", "one", "two"];
a[0]; // "zero"
a[3] = "three"; // extends the array; a.length becomes 4
a.length; // 4 -- always one greater than the highest index used
Reading past the end of the array (or a hole within it) returns undefined rather than throwing.
Sparse Arrays
A sparse array is one whose indices are not contiguous — it has "holes" where no element (not even
undefined) was ever assigned. [1, , 3] and new Array(10) are both sparse: the former has a hole at index 1,
the latter has ten holes and no assigned elements at all.
let sparse = [1, , 3];
sparse.length; // 3
1 in sparse; // false -- index 1 was never assigned
sparse[1]; // undefined (same value you'd get for any missing property)
Most array methods (forEach, map, filter, for…of) skip holes entirely rather than visiting them as
undefined, which is a common source of subtle bugs when an array is expected to be dense. Prefer array
literals with explicit values, or Array.from({ length: n }), over new Array(n) when you need every index
populated.
Array-Like Objects
An array-like object is a plain object that has a numeric length property and indexed properties (0, 1,
2, …) but is not actually an Array instance — it doesn’t inherit Array.prototype, so none of the array
methods below are available on it directly. The classic example is the arguments object inside a
non-arrow function, and DOM APIs such as document.querySelectorAll() return a similar (though iterable)
NodeList.
function sumArgs() {
// `arguments` is array-like, not a real array
return Array.from(arguments).reduce((total, n) => total + n, 0);
}
Array.from() (shown above) and the spread operator (only when the array-like object is also iterable) are the
standard ways to convert an array-like object into a real array so the methods below become available.
Array Methods
The following methods are the ones reached for daily. Each takes the array they’re called on as this and, for
the callback-based methods, invokes the callback as callback(element, index, array).
| Method | What it does | Example |
|---|---|---|
|
Returns a new array with `fn’s return value in place of each element. |
|
|
Returns a new array containing only the elements for which |
|
|
Folds the array down to a single value, calling |
|
|
Calls |
|
|
Returns the first element (or its index) for which |
|
|
Returns |
|
|
Sorts the array in place (and returns it). Without a comparator, elements are sorted as strings — always pass one for numeric data. |
|
|
Returns a new array copying elements from |
|
|
Modifies the array in place: removes |
|
|
Returns a new array with nested arrays flattened up to |
|
|
Equivalent to |
|
|
Returns |
|
Combined with the spread operator (…) for copying/merging arrays ([…a, …b]) and array/object
destructuring for pulling values back out (see Objects &
Destructuring), these methods cover the large majority of everyday array manipulation without ever needing an
explicit for loop.
Typed Arrays and Binary Data
A typed array is a fixed-length, fixed-type array backed directly by a raw block of memory (an
ArrayBuffer), used when working with binary data rather than arbitrary JavaScript values: file formats, network
protocols, cryptography, audio sample buffers, and pixel data from <canvas> or WebGL (see
Canvas, WebGL & Three.js). Unlike a regular Array, every element
of a typed array is constrained to a single numeric type and the array cannot grow or shrink.
Typed Array Types
JavaScript defines one typed array constructor per numeric storage format:
| Constructor | Bytes/element | Range |
|---|---|---|
|
1 |
-128..127 / 0..255 |
|
1 |
0..255, out-of-range writes clamp instead of wrapping (used for canvas pixel data) |
|
2 |
-32768..32767 / 0..65535 |
|
4 |
~-2.1 billion..2.1 billion / 0..~4.3 billion |
|
4 / 8 |
IEEE-754 single/double-precision floating point |
|
8 |
64-bit signed/unsigned integers, as |
Creating and Using Typed Arrays
Typed arrays can be created directly from a length or an iterable, or as a "view" over an existing
ArrayBuffer:
let floats = new Float64Array(4); // 4 zeroed 64-bit floats, backed by a new ArrayBuffer
let ints = Int32Array.from([1, 2, 3]); // like Array.from(), but typed
let buffer = new ArrayBuffer(16); // 16 raw bytes
let view1 = new Int32Array(buffer); // 4 elements, viewing the whole buffer
let view2 = new Uint8Array(buffer, 4, 8); // 8 elements, viewing bytes 4..11 of the same buffer
Because two typed arrays can be views over the same ArrayBuffer, writing through one is visible through the
other — a useful property for reinterpreting the same bytes as different types (e.g. reading a 32-bit integer
as four individual bytes).
Once created, typed arrays support many of the same methods as regular arrays — map, filter, slice,
forEach, sort, includes, and more — with the caveat that map/filter/slice return a new typed array of
the same type rather than a generic Array.
DataView and Endianness
ArrayBuffer views like Int32Array interpret bytes using the platform’s native byte order (endianness),
which can differ between systems. DataView gives explicit, endianness-aware read/write access to a buffer’s
bytes, which matters when parsing a binary format (a network protocol, a file format) that specifies its own
byte order:
let buffer = new ArrayBuffer(4);
let view = new DataView(buffer);
view.setUint32(0, 0x11223344, false); // false = big-endian (the default for most binary file formats)
view.getUint8(0); // 0x11 -- the most-significant byte comes first
view.setUint32(0, 0x11223344, true); // true = little-endian
view.getUint8(0); // 0x44 -- the least-significant byte comes first
DataView is the right tool whenever the byte order of the data you’re reading is fixed by an external format
rather than left to the current platform.