ESC

Type to search the knowledge base.

Typed Arrays and ArrayBuffer

Binary data in JS: ArrayBuffer, views (Uint8Array, DataView), endianness, slices vs subarray, and worker transfer.

advanced3 min read
  • javascript
  • typed-arrays

JS arrays are flexible and heavy. Binary protocols, WebGL, audio, WASM, and file I/O need raw bytes. ArrayBuffer is a fixed-length chunk of memory; typed array views and DataView read/write that memory with types.

const buf = new ArrayBuffer(16); // 16 bytes
const bytes = new Uint8Array(buf);
bytes[0] = 255;
bytes[1] = 1;

const words = new Uint32Array(buf);
// words and bytes share the same memory — reinterpret cast

Common views

Type Bytes/element Range (approx)
Uint8Array 1 0…255
Int8Array 1 -128…127
Uint16Array / Int16Array 2 …
Uint32Array / Int32Array 4 …
Float32Array / Float64Array 4 / 8 IEEE floats
BigInt64Array / BigUint64Array 8 bigint elements
const f32 = new Float32Array([1.5, 2.5]);
f32.buffer; // underlying ArrayBuffer
f32.byteOffset;
f32.byteLength;

DataView for mixed layouts / endianness

Protocols interleave fields; endianness matters on the wire.

const buf = new ArrayBuffer(8);
const view = new DataView(buf);
view.setUint16(0, 0x1234, false); // big-endian
view.setFloat32(2, 3.14, true);   // little-endian at offset 2
view.getUint16(0, false); // 0x1234

Typed arrays use the platform endianness for multi-byte elements; DataView makes endian explicit.

slice vs subarray

const u8 = new Uint8Array([1, 2, 3, 4]);
const sub = u8.subarray(1, 3); // view same buffer [2,3]
sub[0] = 99;
u8[1]; // 99

const copy = u8.slice(1, 3); // new buffer copy

subarray is cheap sharing; slice allocates.

Detach / transfer

const buf = new ArrayBuffer(1024);
worker.postMessage(buf, [buf]); // transfer
// buf.byteLength === 0 in sender — detached

structuredClone(buf, { transfer: [buf] }) same idea. Zero-copy moves for large media.

Text vs binary

const u8 = new TextEncoder().encode('hi'); // Uint8Array
const s = new TextDecoder().decode(u8);

Fetch: await res.arrayBuffer() / await res.bytes() (newer) for binary responses.

When to use

  • Parsing binary file formats
  • WebSocket ArrayBuffer messages
  • Canvas pixel buffers
  • Crypto subtle APIs
  • Interop with WASM memory

Don’t replace normal JS arrays for lists of objects — typed arrays are for homogeneous numbers/bytes.

Interview answer (out loud)

“ArrayBuffer is raw memory; typed arrays are typed views over it; DataView reads mixed fields with explicit endianness. subarray shares memory, slice copies. Buffers can be transferred to workers for zero-copy. I use TextEncoder/Decoder for UTF-8 at the edges.”

Alignment

Multi-byte views need offsets aligned to element size when using typed array constructors on a buffer with byteOffset; DataView is more forgiving for unaligned protocol fields.

// May throw if offset not aligned for Uint32Array
// new Uint32Array(buf, 1, 1);

Cloning views

const a = new Uint8Array([1, 2, 3]);
const b = new Uint8Array(a); // copy
const c = a.slice(); // copy

new Uint8Array(a.buffer) shares memory — know which constructor args copy.

WASM memory

WebAssembly linear memory is an ArrayBuffer (or shared variant). Typed arrays are how JS reads WASM heaps — bounds checks still matter for safety at the app layer.

Further reading

Related guides