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

map(fn)

Returns a new array with `fn’s return value in place of each element.

[1, 2, 3].map(n ⇒ n * 2)[2, 4, 6]

filter(fn)

Returns a new array containing only the elements for which fn returned truthy.

[1, 2, 3, 4].filter(n ⇒ n % 2 === 0)[2, 4]

reduce(fn, initial)

Folds the array down to a single value, calling fn(accumulator, element, index, array) left to right.

[1, 2, 3].reduce((sum, n) ⇒ sum + n, 0)6

forEach(fn)

Calls fn once per element for its side effects; always returns undefined.

[1, 2].forEach(n ⇒ console.log(n))

find(fn) / findIndex(fn)

Returns the first element (or its index) for which fn returns truthy, or undefined/-1 if none does.

[5, 12, 8].find(n ⇒ n > 10)12

some(fn) / every(fn)

Returns true if fn returns truthy for at least one element / for every element.

[1, 2, 3].some(n ⇒ n > 2)true

sort(compareFn?)

Sorts the array in place (and returns it). Without a comparator, elements are sorted as strings — always pass one for numeric data.

[10, 2, 1].sort((a, b) ⇒ a - b)[1, 2, 10]

slice(start, end?)

Returns a new array copying elements from start up to (not including) end; does not modify the original.

[1, 2, 3, 4].slice(1, 3)[2, 3]

splice(start, deleteCount, …​items)

Modifies the array in place: removes deleteCount elements starting at start and inserts items there; returns the removed elements.

let a = [1, 2, 3]; a.splice(1, 1, "x", "y")a is [1, "x", "y", 3]

flat(depth = 1)

Returns a new array with nested arrays flattened up to depth levels.

[1, [2, [3, 4]]].flat(2)[1, 2, 3, 4]

flatMap(fn)

Equivalent to map(fn).flat(1), but more efficient — maps then flattens one level.

[1, 2].flatMap(n ⇒ [n, n * 10])[1, 10, 2, 20]

includes(value)

Returns true/false for whether value occurs in the array (uses ===-like comparison, but treats NaN as equal to itself, unlike indexOf).

[1, NaN, 3].includes(NaN)true

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

Int8Array / Uint8Array

1

-128..127 / 0..255

Uint8ClampedArray

1

0..255, out-of-range writes clamp instead of wrapping (used for canvas pixel data)

Int16Array / Uint16Array

2

-32768..32767 / 0..65535

Int32Array / Uint32Array

4

~-2.1 billion..2.1 billion / 0..~4.3 billion

Float32Array / Float64Array

4 / 8

IEEE-754 single/double-precision floating point

BigInt64Array / BigUint64Array

8

64-bit signed/unsigned integers, as BigInt values

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.