Understanding ArrayBuffer, TypedArray, DataView, and Blob in JavaScript
The article explains how JavaScript handles binary data by using ArrayBuffer as raw memory, TypedArray and DataView as typed views for reading and writing with endianness control, and Blob for file‑like binary objects, detailing their constructors, methods, and typical use cases such as WebGL, file upload, and image display.
Preface
In most computers binary data is stored as byte arrays. In C# this is represented by byte[] . Standard C does not have a dedicated byte type, but it can be created with typedef unsigned char byte . JavaScript originally had a vague concept of bytes and could only represent binary data with ordinary arrays.
With the emergence of WebGL, browsers need to exchange large amounts of binary data with the GPU in real time. Textual formats are insufficient, so a binary interface is required. Typed Arrays were introduced to meet this need, and they are built on top of the ArrayBuffer object.
1. ArrayBuffer
1.1 Basic Concept
The ArrayBuffer object became part of the official ECMAScript specification in ES6. It provides an interface for handling binary data in JavaScript. An ArrayBuffer represents a block of raw memory and cannot be read or written directly; access must be performed through views ( TypedArray views or DataView ).
"ArrayBuffer is essentially a chunk of memory that you cannot use directly. It is similar to malloc in C: you allocate memory and then create a view such as Uint32Array or Int16Array to interpret that memory. MDN describes it as ‘multiple views on the same data’. Any read/write through a view is reflected in the underlying ArrayBuffer ."
1.2 Basic Operations
Syntax
new ArrayBuffer(length)Parameter : length – the size of the buffer to create, in bytes.
Return value : an ArrayBuffer instance.
Exception : throws RangeError if length is greater than Number.MAX_SAFE_INTEGER (≥ 2⁵³) or is negative.
Example
const buffer = new ArrayBuffer(32);
buffer.byteLength; // 32
const v = new Int32Array(buffer);
ArrayBuffer.isView(v); // true
const buffer2 = buffer.slice(0, 1);The example shows a buffer occupying 32 bytes. It has the instance property byteLength , a static method ArrayBuffer.isView() to test whether an object is a TypedArray or DataView , and an instance method slice() that copies a portion of the memory (similar to Array.prototype.slice ).
2. Views
2.1 TypedArray
TypedArray consists of nine constructor functions (the DataView does not support Uint8ClampedArray ).
Name
Description
Bytes per element
Int8Array
8‑bit signed integer
1
Uint8Array
8‑bit unsigned integer
1
Uint8ClampedArray
8‑bit unsigned integer clamped to 0‑255
1
Int16Array
16‑bit signed integer
2
Uint16Array
16‑bit unsigned integer
2
Int32Array
32‑bit signed integer
4
Uint32Array
32‑bit unsigned integer
4
Float32Array
32‑bit IEEE floating point
4
Float64Array
64‑bit IEEE floating point
8
Each view has a constant BYTES_PER_ELEMENT indicating the size of its element type.
Int8Array.BYTES_PER_ELEMENT // 1
Uint8Array.BYTES_PER_ELEMENT // 1
Int16Array.BYTES_PER_ELEMENT // 2
Uint16Array.BYTES_PER_ELEMENT // 2
Int32Array.BYTES_PER_ELEMENT // 4
Uint32Array.BYTES_PER_ELEMENT // 4
Float32Array.BYTES_PER_ELEMENT // 4
Float64Array.BYTES_PER_ELEMENT // 8All nine constructors produce what is collectively called a TypedArray view. They behave like normal arrays (they have a length property and support the usual array methods), but each element has a fixed data type.
Conversion between TypedArray and ordinary arrays:
const typedArray = new Uint8Array([1, 2, 3, 4]);
const normalArray = Array.apply([], typedArray);Creating TypedArray views on an ArrayBuffer :
// Create an 8‑byte buffer
const a = new ArrayBuffer(8);
// Int32 view starting at byte 0, covering the whole buffer
const a1 = new Int32Array(a);
// Uint8 view starting at byte 4
const a2 = new Uint8Array(a, 4);
// Int16 view starting at byte 4, length 2 elements
const a3 = new Int16Array(a, 4, 2);The view constructor accepts three arguments: the underlying ArrayBuffer , an optional byte offset (default 0), and an optional length (default to the end of the buffer).
Example of writing with an Int16Array view and reading with an Int8Array view (demonstrating little‑endian ordering on x86 CPUs):
const buffer = new ArrayBuffer(8);
const int16View = new Int16Array(buffer);
for (let i = 0; i < int16View.length; i++) {
int16View[i] = i * 2;
}
console.log(int16View); // [0, 2, 4, 6]
const int8View = new Int8Array(buffer);
for (let i = 0; i < int8View.length; i++) {
int8View[i] = i;
}
console.log(int8View); // [0, 0, 2, 0, 4, 0, 6, 0]Because the platform uses little‑endian byte order, the most significant byte is stored at the higher address, producing the above results.
2.2 DataView
DataView provides a low‑level interface to read and write multiple numeric types from an ArrayBuffer without worrying about platform endianness.
Endianness (byte order) determines how multi‑byte values are stored. Little‑endian stores the least‑significant byte first; big‑endian stores the most‑significant byte first. Network protocols usually use big‑endian, while most desktop CPUs use little‑endian.
Syntax
new DataView(buffer [, byteOffset [, byteLength]])buffer : an ArrayBuffer or SharedArrayBuffer .
byteOffset (optional): the offset, in bytes, of the first byte of the view. Defaults to 0.
byteLength (optional): the length of the view in bytes. Defaults to the remainder of the buffer.
Example
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer, 0);
view.setInt8(1, 68);
view.getInt8(1); // 68When reading or writing values that span more than one byte, you must specify the desired endianness. DataView methods default to big‑endian; passing true as the third (or second) argument selects little‑endian.
const buffer = new ArrayBuffer(24);
const dv = new DataView(buffer);
// 1 byte, default big‑endian
const v1 = dv.getUint8(0);
// 2 bytes, little‑endian
const v2 = dv.getUint16(1, true);
// 2 bytes, big‑endian
const v3 = dv.getUint16(3, false);
// Write a 32‑bit integer (value 11) at byte 4, little‑endian
dv.setInt32(4, 11, true);3. Blob
3.1 Basic Introduction
The Blob object is commonly used for file upload and file read/write operations. A File object inherits all Blob properties, so a File can be regarded as a special kind of Blob .
Difference from ArrayBuffer : Blob is for handling binary files, while ArrayBuffer operates directly on memory.
Syntax
const blob = new Blob(array [, options]);array : a string or binary object that forms the content of the new Blob .
options (optional): commonly the type property indicating the MIME type.
Example
const array = ['
Hello World!
'];
const blob = new Blob(array, {type: 'text/html'});Properties and Methods
A Blob has size and type properties and several methods such as slice() (to copy a portion of the data) and arrayBuffer() (returns a Promise that resolves with an ArrayBuffer containing the blob’s data).
const blob = new Blob([]);
blob.slice(0, 1);
blob.arrayBuffer().then(buffer => {/* process ArrayBuffer data */});3.2 Application Scenarios
Using window.URL.createObjectURL(blob) you can turn a Blob into a Blob URL for file download or image display within the browser. Blob URLs exist only inside the browser and are not suitable for server‑side storage.
Typical use cases illustrated in the original article include:
File download
Image display
Slice upload (splitting large files into chunks)
Local file reading
4. References
• "Understanding ES6 TypedArray and DataView" • "Discussing JavaScript's Binary Family: Blob, ArrayBuffer, and Buffer" • "ECMAScript 6 Introduction"
Youzan Coder
Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.