JavaScript - JavaScript Typed Arrays and ArrayBuffer

JavaScript is commonly used to work with normal data types such as strings, numbers, objects, and regular arrays. However, some applications need to work directly with binary data. Examples include image processing, audio and video processing, file handling, network communication, game development, cryptography, and communication with hardware devices.

For these situations, JavaScript provides ArrayBuffer, Typed Arrays, and DataView. These features allow JavaScript programs to store and manipulate raw binary data efficiently.

1. What Is Binary Data?

Binary data is information represented internally using sequences of 0s and 1s. Computers use binary representation to store almost everything, including:

  • Images

  • Audio files

  • Video files

  • PDF files

  • Network packets

  • Compressed files

  • Database data

  • Hardware information

For example, a byte contains 8 bits:

01001000

The binary value above represents the decimal number 72.

Traditional JavaScript arrays are not specifically designed for efficiently handling raw binary memory. This is where typed arrays and ArrayBuffer become useful.


2. What Is ArrayBuffer?

An ArrayBuffer is an object that represents a fixed-length block of raw binary memory.

It provides memory storage but does not directly provide a convenient way to read individual values from that memory.

For example:

const buffer = new ArrayBuffer(8);

console.log(buffer.byteLength);

Output:

8

Here:

new ArrayBuffer(8)

creates a memory block containing 8 bytes.

One important point is that an ArrayBuffer represents the memory itself. To actually read or modify the values stored inside it, we normally use a typed array or DataView.


3. Understanding Bytes

A byte consists of 8 bits.

Therefore:

1 byte = 8 bits

The number of possible values in one unsigned byte is:

0 to 255

This is because:

2^8 = 256

and the values start from 0.

For example:

0
1
2
...
254
255

A typed array determines how the bytes in an ArrayBuffer should be interpreted.


4. What Are Typed Arrays?

Typed arrays are special JavaScript objects designed to work with binary data.

Unlike regular arrays, typed arrays contain elements of a specific numeric type.

Common typed arrays include:

Typed Array Data Type Bytes per Element
Int8Array Signed 8-bit integer 1
Uint8Array Unsigned 8-bit integer 1
Uint8ClampedArray Clamped unsigned 8-bit integer 1
Int16Array Signed 16-bit integer 2
Uint16Array Unsigned 16-bit integer 2
Int32Array Signed 32-bit integer 4
Uint32Array Unsigned 32-bit integer 4
Float32Array 32-bit floating-point number 4
Float64Array 64-bit floating-point number 8
BigInt64Array 64-bit signed BigInt 8
BigUint64Array 64-bit unsigned BigInt 8

The type determines how the underlying bytes are interpreted.


5. Creating a Uint8Array

One of the most commonly used typed arrays is Uint8Array.

The Uint8 name means:

  • U = Unsigned

  • Int = Integer

  • 8 = 8 bits

Therefore, each element can contain a value from:

0 to 255

Example:

const numbers = new Uint8Array(4);

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;

console.log(numbers);

Output:

Uint8Array(4) [10, 20, 30, 40]

Each element occupies exactly one byte.


6. Creating a Typed Array from an Array

A typed array can also be created from an ordinary JavaScript array.

const numbers = new Uint8Array([10, 20, 30, 40]);

console.log(numbers);

Output:

Uint8Array(4) [10, 20, 30, 40]

The values are stored using the rules of Uint8Array.

For example:

const numbers = new Uint8Array([100, 200, 300]);

console.log(numbers);

The value 300 cannot be represented directly in an unsigned 8-bit integer because the maximum value is 255. The value is therefore converted according to typed-array rules.


7. Connecting a Typed Array to an ArrayBuffer

A particularly important feature is that a typed array can provide a view of an existing ArrayBuffer.

const buffer = new ArrayBuffer(4);

const numbers = new Uint8Array(buffer);

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;

console.log(numbers);

Here there are two related objects:

ArrayBuffer
    |
    | underlying memory
    |
Uint8Array
    |
    | interprets the memory as 8-bit unsigned integers

The ArrayBuffer provides the memory, while Uint8Array provides a way to access that memory.


8. ArrayBuffer Does Not Store Regular JavaScript Values

It is important to understand that ArrayBuffer is not a normal JavaScript array.

For example:

const buffer = new ArrayBuffer(4);

console.log(buffer[0]);

This does not provide the first byte in the way a normal array would.

Instead, create a view:

const view = new Uint8Array(buffer);

console.log(view[0]);

Now the memory can be accessed through the typed array.


9. Typed Arrays Have Fixed Types

A regular JavaScript array can contain different types of values:

const data = [10, "Hello", true, 25.5];

A typed array is designed for a particular numeric representation.

For example:

const data = new Int16Array(3);

data[0] = 100;
data[1] = 200;
data[2] = 300;

All three elements are represented as 16-bit signed integers.


10. Signed and Unsigned Integers

Typed arrays can use either signed or unsigned integers.

For example:

Int8Array

uses signed 8-bit integers.

Its range is:

-128 to 127

On the other hand:

Uint8Array

uses unsigned 8-bit integers.

Its range is:

0 to 255

Example:

const signed = new Int8Array(2);

signed[0] = -100;
signed[1] = 100;

console.log(signed);

The values are interpreted as signed 8-bit integers.


11. Int16Array

Int16Array stores signed 16-bit integers.

Each element occupies:

2 bytes

Its range is:

-32,768 to 32,767

Example:

const values = new Int16Array(3);

values[0] = -1000;
values[1] = 5000;
values[2] = 30000;

console.log(values);

This is useful when data needs more range than an 8-bit integer provides.


12. Int32Array

Int32Array stores signed 32-bit integers.

Each element requires:

4 bytes

Example:

const values = new Int32Array([100000, 200000, 300000]);

console.log(values);

It is useful when working with binary data that uses 32-bit integer values.


13. Floating-Point Typed Arrays

Typed arrays are not limited to integers.

JavaScript also provides:

Float32Array

and:

Float64Array

For example:

const temperatures = new Float32Array(3);

temperatures[0] = 23.5;
temperatures[1] = 24.7;
temperatures[2] = 25.9;

console.log(temperatures);

Float32Array stores each value using 32-bit floating-point representation.

Float64Array uses 64 bits and provides greater precision.


14. Understanding Byte Length

Typed arrays provide the byteLength property.

Example:

const numbers = new Uint16Array(5);

console.log(numbers.byteLength);

Each Uint16Array element requires 2 bytes.

Therefore:

5 × 2 = 10 bytes

Output:

10

Similarly:

const numbers = new Float64Array(5);

console.log(numbers.byteLength);

Each element requires 8 bytes:

5 × 8 = 40 bytes

15. The buffer Property

A typed array has a buffer property that provides access to its underlying ArrayBuffer.

Example:

const buffer = new ArrayBuffer(8);

const numbers = new Uint8Array(buffer);

console.log(numbers.buffer);

This relationship is important when different views need to work with the same memory.


16. Multiple Views of the Same Buffer

One ArrayBuffer can be viewed using different typed arrays.

Example:

const buffer = new ArrayBuffer(8);

const bytes = new Uint8Array(buffer);
const integers = new Int32Array(buffer);

bytes[0] = 10;

console.log(bytes[0]);
console.log(integers[0]);

Both views refer to the same underlying memory.

Changing the memory through one view can therefore affect what another view sees.

This is useful when processing binary structures that contain different types of data.


17. Byte Offset

A typed array can start at a specific position within an ArrayBuffer.

Example:

const buffer = new ArrayBuffer(10);

const view = new Uint8Array(buffer, 2, 4);

console.log(view.byteOffset);
console.log(view.length);

Here:

ArrayBuffer size = 10 bytes
Starting position = 2 bytes
Number of elements = 4

So the typed array works with bytes from positions:

2, 3, 4, 5

This allows different parts of the same binary buffer to be interpreted separately.


18. Uint8ClampedArray

Uint8ClampedArray is another 8-bit typed array.

It stores values between:

0 and 255

However, unlike Uint8Array, values outside this range are clamped.

For example:

const values = new Uint8ClampedArray(3);

values[0] = -20;
values[1] = 100;
values[2] = 300;

console.log(values);

Values below 0 are converted toward 0, while values above 255 are converted toward 255.

Uint8ClampedArray is particularly important in image processing because pixel color channels commonly use values from 0 to 255.


19. Typed Arrays and Images

A digital image is ultimately represented as binary data.

For an RGBA image, each pixel commonly contains four values:

Red
Green
Blue
Alpha

Each value can be represented using one byte.

For example:

255  0  0  255

could represent a fully opaque red pixel.

JavaScript can represent such pixel data using:

Uint8ClampedArray

This is one reason Uint8ClampedArray is commonly encountered with the Canvas API.


20. DataView

DataView is another way to work with an ArrayBuffer.

Unlike a typed array, DataView allows you to read different types of values from the same buffer.

Example:

const buffer = new ArrayBuffer(8);

const view = new DataView(buffer);

view.setInt32(0, 1000);

console.log(view.getInt32(0));

Output:

1000

Here:

setInt32()

writes a 32-bit signed integer, while:

getInt32()

reads it.


21. DataView and Different Data Types

DataView provides methods such as:

getInt8()
getUint8()
getInt16()
getUint16()
getInt32()
getUint32()
getFloat32()
getFloat64()

It also provides corresponding setter methods:

setInt8()
setUint8()
setInt16()
setUint16()
setInt32()
setUint32()
setFloat32()
setFloat64()

This gives developers precise control over binary data.


22. Endianness

When multiple bytes represent a single number, the order in which those bytes are stored matters.

This is called endianness.

The two common forms are:

Big-endian
Little-endian

For example, suppose a number occupies four bytes:

01 02 03 04

Different byte-order systems can interpret those bytes differently.

DataView allows you to explicitly specify the byte order.

Example:

const buffer = new ArrayBuffer(4);

const view = new DataView(buffer);

view.setUint32(0, 305419896, true);

console.log(view.getUint32(0, true));

The final true indicates little-endian interpretation.

This becomes especially important when JavaScript communicates with systems that use a specific binary format.


23. Typed Arrays Versus Regular Arrays

There are important differences between normal arrays and typed arrays.

Feature Regular Array Typed Array
Data types Can contain mixed values Numeric type is defined
Memory representation General-purpose Binary-oriented
Fixed element type No Yes
Fixed length No Yes
Binary data handling Less suitable Designed for it
Memory efficiency Generally less predictable More compact for numeric data
Common uses General collections Binary and numeric processing

For ordinary application data, regular arrays are usually appropriate.

For raw binary data, typed arrays are often more suitable.


24. Important Typed Array Methods

Typed arrays support many familiar array operations.

For example:

const numbers = new Uint8Array([10, 20, 30, 40]);

console.log(numbers.length);
console.log(numbers[1]);

You can also use methods such as:

numbers.map()
numbers.filter()
numbers.reduce()
numbers.slice()
numbers.subarray()

Example:

const numbers = new Uint8Array([10, 20, 30]);

const doubled = numbers.map(value => value * 2);

console.log(doubled);

Output:

Uint8Array(3) [20, 40, 60]

25. slice() and subarray()

Typed arrays provide both slice() and subarray(), but their behavior is important to understand.

slice() creates a new typed array containing copied elements.

const numbers = new Uint8Array([10, 20, 30, 40]);

const part = numbers.slice(1, 3);

console.log(part);

Output:

Uint8Array(2) [20, 30]

subarray() creates a new view over the same underlying memory.

const numbers = new Uint8Array([10, 20, 30, 40]);

const part = numbers.subarray(1, 3);

console.log(part);

Because the memory is shared, changes to the subarray can affect the original typed array.


26. Converting Typed Arrays

Typed arrays can be converted into normal arrays.

For example:

const typed = new Uint8Array([10, 20, 30]);

const normal = Array.from(typed);

console.log(normal);

Output:

[10, 20, 30]

Another option is:

const normal = [...typed];

This is useful when you need to use the data with APIs that expect ordinary JavaScript arrays.


27. Using Typed Arrays for Binary Files

Typed arrays are useful when a program needs to inspect or modify binary file contents.

For example, a file may contain:

Header
Metadata
Image data
Additional binary information

The program can read the file into an ArrayBuffer and then create views over different sections.

Conceptually:

File
 |
 v
ArrayBuffer
 |
 +---- Header view
 |
 +---- Metadata view
 |
 +---- Data view

This technique is common in applications that process custom binary file formats.


28. Using Typed Arrays in Network Communication

Network protocols often transmit binary information.

Instead of representing every byte as a separate general-purpose JavaScript value, binary data can be represented using:

ArrayBuffer
Uint8Array
DataView

For example:

const packet = new Uint8Array([1, 2, 3, 4]);

The array represents four bytes of binary information.

This can be useful when implementing or processing binary network protocols.


29. Using Typed Arrays with Audio

Audio applications often process large quantities of numerical samples.

For example, audio data may contain values such as:

0.12
-0.35
0.52
-0.18

Floating-point typed arrays such as:

Float32Array

are commonly useful for representing this type of numerical data.

They provide a compact and predictable representation for large sequences of numeric samples.


30. Using Typed Arrays in Web Applications

Typed arrays are useful in many areas of modern JavaScript development, including:

Image processing
Audio processing
Video processing
File processing
Network protocols
Cryptography
Game development
Scientific calculations
Machine learning
WebGL
WebAssembly

They are particularly valuable when performance and predictable binary representation are important.


31. Simple Practical Example

Consider a program that needs to store five unsigned bytes.

const buffer = new ArrayBuffer(5);

const data = new Uint8Array(buffer);

data[0] = 10;
data[1] = 20;
data[2] = 30;
data[3] = 40;
data[4] = 50;

console.log(data);

The memory can be visualized as:

Byte 0    Byte 1    Byte 2    Byte 3    Byte 4
  10        20        30        40        50

The ArrayBuffer provides the five bytes of memory, while Uint8Array provides access to each byte.


32. Another Practical Example Using DataView

Suppose a binary structure contains a 16-bit number followed by a 32-bit number.

const buffer = new ArrayBuffer(6);

const view = new DataView(buffer);

view.setUint16(0, 500);
view.setUint32(2, 100000);

console.log(view.getUint16(0));
console.log(view.getUint32(2));

Output:

500
100000

This approach is useful for interpreting structured binary formats where different sections contain different numeric types.


33. Advantages of Typed Arrays

Typed arrays provide several important benefits.

Predictable Data Representation

Each element has a specific binary representation.

Efficient Numeric Storage

Typed arrays can store large quantities of numeric data in a compact form.

Binary Data Processing

They are specifically designed for working with raw bytes and binary structures.

Better Control

Developers can control the size and representation of numeric values.

Shared Memory Views

Multiple typed arrays or DataView objects can operate on the same ArrayBuffer.

Useful for Performance-Sensitive Applications

They are especially valuable when applications process large amounts of numerical or binary data.


34. Limitations

Typed arrays are not replacements for normal JavaScript arrays in every situation.

They have restrictions such as:

  • Their length is fixed.

  • Their elements have a specific numeric representation.

  • They are primarily intended for numeric and binary data.

  • Values outside the supported range are converted according to the typed-array rules.

  • Some normal array behaviors do not apply in exactly the same way.

Therefore, choosing between a regular array and a typed array depends on the application.


35. ArrayBuffer vs Typed Array vs DataView

The three concepts can be summarized as follows:

Feature Purpose
ArrayBuffer Provides raw binary memory
Typed Array Provides a typed view of that memory
DataView Provides flexible access to different binary data types

A useful way to remember them is:

ArrayBuffer
    |
    | stores raw memory
    v
Typed Array / DataView
    |
    | interprets and accesses the memory
    v
Application data

For example:

const buffer = new ArrayBuffer(8);

const numbers = new Uint8Array(buffer);

Here buffer represents the memory and numbers represents a particular interpretation of that memory.


36. Conclusion

ArrayBuffer, Typed Arrays, and DataView form an important part of JavaScript's binary-data capabilities.

An ArrayBuffer provides a fixed-size block of raw memory. Typed arrays such as Uint8Array, Int32Array, and Float32Array provide specialized ways to interpret and manipulate that memory. DataView provides more flexible control when a binary structure contains different data types or requires explicit control over byte order.

These features are particularly important in advanced JavaScript applications involving files, images, audio, networking, cryptography, graphics, WebAssembly, and high-performance numerical processing.

Understanding the relationship between memory, bytes, typed views, and binary representation is essential for working effectively with low-level data in JavaScript.