JS: ArrayBuffer
ai answer
JavaScript ArrayBuffer Tutorial
What is an ArrayBuffer?
ArrayBuffer is a built-in JavaScript object that represents a fixed-length raw binary data buffer. It is the foundation for handling binary data in modern JavaScript (especially in browsers and Node.js).
Think of it as a contiguous block of memory (like a byte array) that you can read from and write to using views — most commonly TypedArrays (Uint8Array, Float32Array, etc.) or DataView.
Key characteristics:
- Fixed size (cannot be resized after creation)
- Neutral — it doesn't interpret the data (just raw bytes)
- Used heavily in Web APIs: WebSockets, Fetch (with
arrayBuffer()), WebGL, Web Audio, File API, Web Workers, etc.
Creating an ArrayBuffer
// Create a buffer of 16 bytes (empty, initialized to 0) const buffer = new ArrayBuffer(16); console.log(buffer.byteLength); // 16
You can also create one from existing data using TypedArray or other methods (covered later).
Basic Properties
| Property | Description |
|---|---|
byteLength |
Size of the buffer in bytes (read-only) |
byteOffset |
(On views) offset from start of buffer |
detached |
true if the buffer was transferred/detached (ES2021+) |
const buf = new ArrayBuffer(32); console.log(buf.byteLength); // 32
Views: Typed Arrays and DataView
You cannot directly read/write an ArrayBuffer. You must create a view.
1. Typed Arrays (most common)
const buffer = new ArrayBuffer(16); // Create different typed views on the same buffer const uint8 = new Uint8Array(buffer); // unsigned 8-bit integers (bytes) const int16 = new Int16Array(buffer); // signed 16-bit integers const float32 = new Float32Array(buffer); // 32-bit floats uint8[0] = 255; // Set first byte console.log(uint8[0]); // 255 console.log(int16[0]); // Depends on endianness (usually -1 for signed)
Common Typed Arrays:
Uint8Array/Int8Array— bytesUint16Array/Int16ArrayUint32Array/Int32ArrayFloat32Array/Float64ArrayBigUint64Array/BigInt64Array(for 64-bit integers)
2. DataView (for mixed types & explicit endianness)
Use DataView when you need fine-grained control:
const buffer = new ArrayBuffer(16); const view = new DataView(buffer); view.setUint8(0, 255); view.setInt16(1, 300, false); // big-endian (network byte order) view.setFloat32(4, 3.14, true); // little-endian console.log(view.getUint8(0)); // 255 console.log(view.getInt16(1, false));
Important Methods & Operations
Slicing
const buffer = new ArrayBuffer(32); const slice = buffer.slice(8, 24); // Creates a **copy** of bytes 8-23
Transfer (zero-copy move) — ES2018+
const buffer1 = new ArrayBuffer(1024); const buffer2 = buffer1.transfer(); // buffer1 becomes detached // Or transfer with limit: const buffer3 = buffer1.transfer(512);
Useful for passing large buffers between workers without copying.
Checking if detached
console.log(buffer1.detached); // true
Converting Between Formats
// String <-> ArrayBuffer function stringToArrayBuffer(str) { return new TextEncoder().encode(str).buffer; } function arrayBufferToString(buf) { return new TextDecoder().decode(new Uint8Array(buf)); } // Blob / File const blob = new Blob([new Uint8Array(buffer)]); const file = new File([buffer], "data.bin"); // Fetch const response = await fetch(url); const arrayBuffer = await response.arrayBuffer();
Practical Examples
1. Reading a File as Binary
input.addEventListener('change', async (e) => { const file = e.target.files[0]; const buffer = await file.arrayBuffer(); const uint8 = new Uint8Array(buffer); console.log(uint8); // raw bytes });
2. Custom Binary Protocol (e.g., game networking)
function createMessage(id, payload) { const buffer = new ArrayBuffer(4 + payload.length); const view = new DataView(buffer); view.setUint32(0, id, false); // 4-byte ID new Uint8Array(buffer, 4).set(payload); // payload return buffer; }
3. Copying data between buffers
const src = new Uint8Array([1, 2, 3, 4]); const dest = new Uint8Array(10); dest.set(src, 3); // copy src starting at index 3 in dest
Common Use Cases
- Networking: WebSockets (send/receive binary frames), WebRTC
- Graphics: WebGL vertex buffers, textures
- Audio: Web Audio API
- Cryptography:
crypto.subtleAPI often works withArrayBuffer - File processing: Parsing images, PDFs, custom formats
- Performance-critical apps: Games, scientific computing, video processing
Best Practices & Gotchas
- Always use views — never assume you can treat
ArrayBufferlike a normal array. - Endianness matters — network protocols are usually big-endian (
falseinDataView). - SharedArrayBuffer — for sharing memory across workers (requires special headers for security).
- Memory management — Large buffers can cause memory pressure. Use
slice()ortransfer()wisely. - TypedArray vs DataView:
- Use TypedArray for speed and simplicity (same type).
- Use DataView for heterogeneous data or explicit control.
- Immutability — Buffers are mutable. Clone with
.slice()if needed. - Node.js vs Browser — Most APIs are identical, but Node has
Bufferclass (which can be created fromArrayBuffer).
Quick Reference Cheat Sheet
new ArrayBuffer(length) buffer.byteLength buffer.slice(begin, end) new Uint8Array(buffer) new DataView(buffer) new TextEncoder().encode(str).buffer new TextDecoder().decode(uint8array)