JavaScript TypedArray Reference
All 11 typed array types, ArrayBuffer, DataView, and SharedArrayBuffer — with byte sizes, value ranges, shared Array methods, and a live code runner
| Type | Bytes | Category |
|---|---|---|
| Int8Array | 1 | Integer (Signed) |
| Uint8Array | 1 | Integer (Unsigned) |
| Uint8ClampedArray | 1 | Integer (Unsigned) |
| Int16Array | 2 | Integer (Signed) |
| Uint16Array | 2 | Integer (Unsigned) |
| Int32Array | 4 | Integer (Signed) |
| Uint32Array | 4 | Integer (Unsigned) |
| Float32Array | 4 | Float |
| Float64Array | 8 | Float |
| BigInt64Array | 8 | BigInt |
| BigUint64Array | 8 | BigInt |
Int8ArrayInteger (Signed)ES2015Uint8ArrayInteger (Unsigned)ES2015Uint8ClampedArrayInteger (Unsigned)ES2015Int16ArrayInteger (Signed)ES2015Uint16ArrayInteger (Unsigned)ES2015Int32ArrayInteger (Signed)ES2015Uint32ArrayInteger (Unsigned)ES2015Float32ArrayFloatES2015Float64ArrayFloatES2015BigInt64ArrayBigIntES2020BigUint64ArrayBigIntES2020You’re processing binary data from a WebSocket — the server sends raw bytes for audio samples, pixel data, or protocol buffers. A regular JavaScript array stores values as 64-bit floats, wasting memory and preventing direct binary manipulation. You need Int16Array for audio samples, Uint8Array for binary protocols, Float32Array for WebGL vertex data — but there are 11 TypedArray types and you keep mixing up which one to use for which byte size and value range.
Why This Reference (Not MDN)
MDN documents TypedArrays, ArrayBuffer, DataView, and SharedArrayBuffer across many pages. This reference puts all 11 types on one page — byte sizes, value ranges, shared Array methods that work on TypedArrays, TypedArray-specific methods, and DataView get/set methods — in a scannable format.
What Are JavaScript TypedArrays?
JavaScript TypedArrays are array-like views into raw binary data stored in an ArrayBuffer. Unlike regular JavaScript arrays, every element in a TypedArray has a fixed type and byte size — making them ideal for performance-critical code, WebGL graphics, audio processing, file parsing, and cryptography.
The core components of the TypedArray ecosystem are:
- ArrayBuffer — a fixed-length raw binary data buffer
- TypedArray — a strongly-typed view into an ArrayBuffer (11 concrete types)
- DataView — a flexible view that supports mixed-type reads/writes with explicit endianness control
- SharedArrayBuffer — like ArrayBuffer but shareable across Web Workers via
Atomics
TypedArrays were introduced in ECMAScript 2015 (ES6) and extended with BigInt64Array and BigUint64Array in ES2020.
The 11 TypedArray Types
| Type | Bytes/Element | Value Range | Use Case |
|---|---|---|---|
Int8Array | 1 | −128 to 127 | Binary data, audio, protocols |
Uint8Array | 1 | 0 to 255 | Images, crypto, file I/O |
Uint8ClampedArray | 1 | 0 to 255 (clamped) | Canvas pixel manipulation |
Int16Array | 2 | −32,768 to 32,767 | Audio PCM, sensors |
Uint16Array | 2 | 0 to 65,535 | WebGL indices, Unicode |
Int32Array | 4 | −2,147,483,648 to 2,147,483,647 | General 32-bit integers |
Uint32Array | 4 | 0 to 4,294,967,295 | Bit masks, packed colors |
Float32Array | 4 | ±3.4×10³⁸ | WebGL vertices, shader data |
Float64Array | 8 | ±1.8×10³⁰⁸ | Scientific computing, finance |
BigInt64Array | 8 | −9.2×10¹⁸ to 9.2×10¹⁸ | 64-bit signed integers |
BigUint64Array | 8 | 0 to 1.8×10¹⁹ | 64-bit unsigned integers |
Choosing the Right TypedArray
The choice depends on precision requirements, memory constraints, and interoperability:
- Need Canvas pixels? →
Uint8ClampedArrayis required by theImageDataAPI - Need WebGL geometry? →
Float32Array(positions/normals),Uint16Array(indices ≤ 65535),Uint32Array(indices > 65535) - Need audio PCM? →
Int16Arrayfor raw audio,Float32Arrayfor Web Audio API - Need file/network binary? →
Uint8Arrayfor byte streams;DataViewfor mixed-type structs - Need JavaScript Number compatibility? →
Float64Array(same precision, no loss) - Need large integers (> 2⁵³)? →
BigInt64ArrayorBigUint64Array
ArrayBuffer: The Binary Container
An ArrayBuffer is a fixed-length block of memory. You cannot directly read or write its bytes — you need a TypedArray or DataView as a “lens”:
// Create a 16-byte buffer
const buf = new ArrayBuffer(16);
console.log(buf.byteLength); // 16
// Create typed views over the same buffer
const u8 = new Uint8Array(buf); // 16 elements
const u16 = new Uint16Array(buf); // 8 elements
const f64 = new Float64Array(buf); // 2 elements
// Writing via one view is visible through others
u8[0] = 0xFF;
console.log(u16[0]); // depends on endianness
Key ArrayBuffer Facts
byteLengthis fixed at construction and cannot change- You can create multiple typed array views over the same buffer (they share memory)
ArrayBuffer.isView(value)returns true for any TypedArray or DataView- To copy a buffer:
buf.slice(0)orbuf.slice(start, end) - Transferring buffers across
postMessagedetaches the original
SharedArrayBuffer: Concurrent Binary Data
SharedArrayBuffer works like ArrayBuffer but can be shared between the main thread and Web Workers without copying:
// Main thread
const sab = new SharedArrayBuffer(1024);
worker.postMessage({ buffer: sab });
// Worker thread — same memory!
const arr = new Int32Array(sab);
Atomics.add(arr, 0, 1); // thread-safe increment
SharedArrayBuffer Requirements
- Requires cross-origin isolation headers:
Cross-Origin-Opener-Policy: same-originandCross-Origin-Embedder-Policy: require-corp - Use
AtomicsAPI for thread-safe operations (read, write, wait, notify) - Without Atomics, reads/writes are not guaranteed to be atomic
DataView: Mixed-Type and Endianness Control
While TypedArrays assume all elements are the same type, DataView lets you read and write different types at arbitrary byte offsets — essential for parsing binary protocols and file formats:
// Parse a hypothetical binary header
// Offset 0: uint16 magic number
// Offset 2: uint32 file size
// Offset 6: float32 version
const buf = fetchBinaryData(); // ArrayBuffer
const dv = new DataView(buf);
const magic = dv.getUint16(0, false); // big-endian
const size = dv.getUint32(2, true); // little-endian
const ver = dv.getFloat32(6, true);
Endianness
Endianness determines the byte order of multi-byte values:
- Big-endian (network byte order): Most significant byte first. Common in network protocols (TCP/IP headers, PNG, JPEG).
- Little-endian (host byte order): Least significant byte first. Used by x86/ARM CPUs, most file formats (BMP, WAV, WebP).
const buf = new ArrayBuffer(4);
const dv = new DataView(buf);
dv.setUint32(0, 0x01020304, false); // big-endian
// Bytes: [0x01, 0x02, 0x03, 0x04]
dv.setUint32(0, 0x01020304, true); // little-endian
// Bytes: [0x04, 0x03, 0x02, 0x01]
Always specify the littleEndian argument in DataView methods — the default (false = big-endian) is easy to forget.
TypedArray-Specific Methods
set(array, offset?)
Efficiently copies data from an array or TypedArray into a target:
const dest = new Uint8Array(10);
dest.set([1, 2, 3]); // copy starting at offset 0
dest.set([4, 5, 6], 3); // copy starting at offset 3
set() can use memcpy-level optimizations and is much faster than element-by-element assignment for large arrays.
subarray(begin?, end?)
Creates a zero-copy view over a portion of the same buffer:
const a = new Uint8Array([1, 2, 3, 4, 5]);
const view = a.subarray(1, 4); // [2, 3, 4] — shares buffer
view[0] = 99;
console.log(a[1]); // 99 — original changed!
Key distinction: subarray() shares the buffer (zero copy), while slice() creates an independent copy.
Shared Array Methods
TypedArrays implement most of the Array prototype methods. The key differences:
map()andfilter()return a TypedArray of the same type (not a plain Array)sort()defaults to numeric comparison —[10, 9, 2].sort()→[2, 9, 10](correct!)- No
push/pop/shift/unshift/splice— TypedArrays are fixed-length - No
flat/flatMap— not supported includes()correctly handlesNaN, unlikeindexOf()
// map returns same type
const f32 = new Float32Array([1, 2, 3]);
const doubled = f32.map(x => x * 2);
console.log(doubled instanceof Float32Array); // true
// sort is numeric by default
const u8 = new Uint8Array([10, 9, 2, 100]);
u8.sort();
console.log(u8); // Uint8Array [2, 9, 10, 100] ✓
// includes handles NaN
const f = new Float32Array([NaN]);
console.log(f.includes(NaN)); // true
console.log(f.indexOf(NaN)); // -1 (broken!)
Common Patterns
Convert Between TypedArray Types
// Int16Array → Float32Array (normalize audio)
const pcm = new Int16Array([-32768, 0, 32767]);
const float = Float32Array.from(pcm, s => s / 32768);
console.log(float); // Float32Array [-1, 0, ~1]
// Uint8Array → Uint16Array (pack two bytes)
const bytes = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
const shorts = new Uint16Array(bytes.buffer);
// Interpretation depends on platform endianness
Copy Buffer Region
// Zero-copy view (subarray)
const full = new Uint8Array(100);
const header = full.subarray(0, 8); // first 8 bytes, shared
const body = full.subarray(8, 90); // next 82 bytes, shared
// Independent copy (slice)
const headerCopy = full.slice(0, 8); // new buffer, not shared
Concatenate TypedArrays
function concat(...arrays) {
const totalLen = arrays.reduce((n, a) => n + a.length, 0);
const result = new Uint8Array(totalLen);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
}
Convert Between Uint8Array and String
// String → Uint8Array (UTF-8)
const encoder = new TextEncoder();
const bytes = encoder.encode('Hello, World!');
// Uint8Array → String (UTF-8)
const decoder = new TextDecoder();
const str = decoder.decode(bytes);
// Uint8Array → base64
const base64 = btoa(String.fromCharCode(...bytes));
// base64 → Uint8Array
const decoded = Uint8Array.from(atob(base64), c => c.charCodeAt(0));
Parse Binary File Format
async function parseBmpHeader(url) {
const res = await fetch(url);
const buf = await res.arrayBuffer();
const dv = new DataView(buf);
return {
signature: String.fromCharCode(dv.getUint8(0), dv.getUint8(1)), // "BM"
fileSize: dv.getUint32(2, true), // little-endian
width: dv.getInt32(18, true),
height: dv.getInt32(22, true),
bitDepth: dv.getUint16(28, true),
};
}
Use with Web Crypto API
// Generate random bytes
const salt = new Uint8Array(16);
crypto.getRandomValues(salt);
// Derive a key
const key = await crypto.subtle.importKey(
'raw', salt, 'HKDF', false, ['deriveKey']
);
// SHA-256 hash
const data = new TextEncoder().encode('secret');
const hashBuf = await crypto.subtle.digest('SHA-256', data);
const hashHex = [...new Uint8Array(hashBuf)]
.map(b => b.toString(16).padStart(2, '0'))
.join('');
Frequently Asked Questions
What is the difference between subarray() and slice()?
subarray() returns a new TypedArray view that references the same underlying ArrayBuffer — no data is copied. Mutations via the subarray are visible in the original. slice() creates a completely independent copy in a new ArrayBuffer. Use subarray() for performance-critical code that does not need isolation, and slice() when you need a truly independent buffer region.
Why does my TypedArray value wrap instead of clamping?
For all TypedArrays except Uint8ClampedArray, out-of-range assignments wrap using modular arithmetic. Writing 256 to a Uint8Array stores 0; writing -1 stores 255. Only Uint8ClampedArray clamps values to [0, 255]. If you need clamping behavior, use Uint8ClampedArray or manually clamp values before assignment: Math.max(0, Math.min(255, value)).
Can I change the size of a TypedArray after creation?
No. TypedArrays are fixed-length — the length is determined at construction and cannot change. There is no equivalent of Array.push() or Array.splice(). To “resize”, create a new larger TypedArray and use .set() to copy the old data.
What is endianness and why does it matter?
Endianness determines how multi-byte values are stored in memory. Big-endian stores the most significant byte first (used in network protocols). Little-endian stores the least significant byte first (used by x86/ARM hardware). When reading binary data from files or network streams, specifying the wrong endianness will produce incorrect values. DataView methods have a littleEndian parameter for explicit control.
When should I use DataView instead of a TypedArray?
Use DataView when:
- The binary data contains mixed types (e.g., a header with uint16 + uint32 + float32 fields)
- You need to control endianness on a per-read basis
- Fields are not naturally aligned (e.g., a 4-byte int at byte offset 1)
- You are parsing a binary file format or network protocol
Use TypedArrays when all elements share the same type and natural alignment, such as WebGL vertex buffers or audio PCM samples.
Can TypedArrays hold BigInt values?
Only BigInt64Array and BigUint64Array store BigInt values. All other TypedArrays store regular JavaScript number. BigInt TypedArray elements use BigInt literals (the n suffix) and cannot be mixed with regular number arithmetic without explicit conversion: Number(bigintValue) or BigInt(numberValue).
How do SharedArrayBuffer and Atomics relate to TypedArrays?
SharedArrayBuffer is an ArrayBuffer that can be shared across Web Workers and the main thread. TypedArray views (especially Int32Array and BigInt64Array) over a SharedArrayBuffer can be used with the Atomics API for thread-safe operations: Atomics.add(), Atomics.compareExchange(), Atomics.wait(), and Atomics.notify(). Without Atomics, concurrent reads/writes to shared memory are subject to data races.
What is the performance benefit of TypedArrays?
TypedArrays provide several performance advantages over regular arrays: (1) elements are stored in contiguous memory with uniform type, enabling CPU cache efficiency; (2) the JavaScript engine can skip type checking and boxing/unboxing; (3) TypedArrays interoperate directly with native APIs (WebGL, Web Audio, WebAssembly) without copying; (4) set() can use bulk memory copy (memcpy) internally. For large datasets (thousands+ elements), TypedArrays can be an order of magnitude faster than regular arrays.