Typed arrays in JavaScript provide a way to work with binary data using arrays of fixed types and sizes. They are particularly useful when interacting with raw binary data from external sources such as files, network operations, or when performing high-performance tasks like real-time audio/video processing, graphics, and data visualization.
Typed arrays consist of buffer objects and view objects:
ArrayBuffer: Represents a fixed-length block of memory.
Typed array views: Allow you to interpret and manipulate the binary data in an ArrayBuffer using specific types like Int8, Uint8, Int16, Float32, etc.
This tutorial will explore how to create and work with typed arrays using practical code examples.
Table of Contents
1. Understanding ArrayBuffer
An ArrayBuffer is a generic, fixed-length binary data buffer. It represents a chunk of memory that can be accessed and manipulated using typed arrays.
Example 1: Creating an ArrayBuffer
// Create an ArrayBuffer of 16 bytes const buffer = new ArrayBuffer(16); console.log(buffer.byteLength); // Output: 16
Explanation:
new ArrayBuffer(16) creates a buffer with 16 bytes.
The byteLength property shows the size of the buffer in bytes.
2. Creating Typed Arrays
Typed arrays are views on an ArrayBuffer that allow you to read and write binary data in a specific format (e.g., Int8, Uint16, Float32). Typed arrays include:
Int8Array, Uint8Array, Uint8ClampedArray: 8-bit signed, unsigned, and clamped integers.
Int16Array, Uint16Array: 16-bit signed and unsigned integers.
Int32Array, Uint32Array: 32-bit signed and unsigned integers.
Float32Array, Float64Array: 32-bit and 64-bit floating-point numbers.
Example 2: Creating a Typed Array (Int8Array)
// Create an ArrayBuffer of 8 bytes const buffer = new ArrayBuffer(8); // Create a view of the buffer as an Int8Array const int8View = new Int8Array(buffer); console.log(int8View.length); // Output: 8 console.log(int8View); // Output: Int8Array(8) [0, 0, 0, 0, 0, 0, 0, 0] // Set values in the typed array int8View[0] = 127; int8View[1] = -128; console.log(int8View); // Output: Int8Array(8) [127, -128, 0, 0, 0, 0, 0, 0]
Explanation:
We create an ArrayBuffer of 8 bytes.
An Int8Array view allows us to interpret each byte of the buffer as an 8-bit signed integer.
The length of the typed array corresponds to the number of elements it can hold based on the buffer size (1 byte per element for Int8Array).
3. Typed Array Views
Typed arrays provide various views to interpret an ArrayBuffer in different formats:
Int8Array: 8-bit signed integers.
Uint8Array: 8-bit unsigned integers.
Int16Array: 16-bit signed integers.
Uint16Array: 16-bit unsigned integers.
Int32Array: 32-bit signed integers.
Uint32Array: 32-bit unsigned integers.
Float32Array: 32-bit floating-point numbers.
Float64Array: 64-bit floating-point numbers.
Example 3: Using Different Typed Array Views on the Same Buffer
const buffer = new ArrayBuffer(4); // Create different typed array views const int8View = new Int8Array(buffer); const int16View = new Int16Array(buffer); const float32View = new Float32Array(buffer); // Set a value using the Int8Array view int8View[0] = 42; console.log(int8View); // Output: Int8Array(4) [42, 0, 0, 0] console.log(int16View); // Output: Int16Array(2) [42, 0] console.log(float32View); // Output: Float32Array(1) [5.885453947183122e-44]
Explanation:
We create an ArrayBuffer of 4 bytes and create different typed array views (Int8Array, Int16Array, Float32Array) on the same buffer.
Modifying the buffer using one view affects the other views, as they share the same memory.
4. Typed Arrays with Initial Values
Typed arrays can be initialized with an array of values directly. In this case, a new ArrayBuffer is created internally.
Example 4: Initializing a Typed Array with Values
// Create a Uint8Array with initial values const uint8Array = new Uint8Array([10, 20, 30, 40, 50]); console.log(uint8Array); // Output: Uint8Array(5) [10, 20, 30, 40, 50] // Accessing elements console.log(uint8Array[2]); // Output: 30 // Modifying elements uint8Array[2] = 99; console.log(uint8Array); // Output: Uint8Array(5) [10, 20, 99, 40, 50]
Explanation:
We create a Uint8Array with initial values [10, 20, 30, 40, 50].
Elements can be accessed and modified using array index notation.
5. Clamped Arrays with Uint8ClampedArray
Uint8ClampedArray is a special type of typed array where values are clamped to the range [0, 255]. If you set a value less than 0, it will be clamped to 0. If you set a value greater than 255, it will be clamped to 255.
Example 5: Using Uint8ClampedArray
const clampedArray = new Uint8ClampedArray(4); // Set values in the clamped array clampedArray[0] = 100; clampedArray[1] = -50; // Will be clamped to 0 clampedArray[2] = 300; // Will be clamped to 255 clampedArray[3] = 200; console.log(clampedArray); // Output: Uint8ClampedArray(4) [100, 0, 255, 200]
Explanation:
Uint8ClampedArray clamps values to the range of 0 to 255.
Setting a value outside this range automatically adjusts it to the nearest valid value.
6. Copying and Slicing Typed Arrays
Typed arrays support set() to copy values from another array and subarray() to create a new view on the existing buffer.
Example 6: Copying and Slicing Typed Arrays
const srcArray = new Uint8Array([10, 20, 30, 40, 50]); const destArray = new Uint8Array(5); // Copy values from `srcArray` to `destArray` destArray.set(srcArray); console.log(destArray); // Output: Uint8Array(5) [10, 20, 30, 40, 50] // Creating a subarray (view on the original buffer) const subArray = srcArray.subarray(1, 4); console.log(subArray); // Output: Uint8Array(3) [20, 30, 40]
Explanation:
The set() method copies values from srcArray to destArray.
The subarray() method creates a new view on the buffer, starting at index 1 and ending before index 4.
7. Endianness and DataView
Binary data can be stored in different byte orders (endianness). The DataView object provides more control over reading and writing data with specific endianness.
Example 7: Using DataView to Handle Endianness
const buffer = new ArrayBuffer(4); const dataView = new DataView(buffer); // Set a 16-bit value at byte offset 0, using little-endian dataView.setUint16(0, 0x1234, true); console.log(dataView.getUint16(0, true)); // Output: 4660 (0x1234 in decimal) console.log(dataView.getUint16(0, false)); // Output: 13330 (byte-swapped)
Explanation:
DataView provides methods to set and get values with control over endianness.
The true or false parameter specifies whether to use little-endian or big-endian byte order.
Conclusion
Typed arrays in JavaScript are a powerful way to handle binary data and perform high-performance operations. They are particularly useful in scenarios like graphics processing, working with audio and video data, interacting with Web APIs, and scientific computing. By using ArrayBuffer and typed array views, you can manage raw binary data efficiently.
Key Points:
ArrayBuffer: Represents a fixed-length block of memory.
Typed Arrays: Views (Int8Array, Uint16Array, Float32Array, etc.) to interpret and manipulate binary data.
Uint8ClampedArray: Automatically clamps values to the range [0, 255].
DataView: Provides low-level access to ArrayBuffer data with specific endianness.
Experiment with different typed arrays and DataView to understand their behavior and how to use them for binary data manipulation in JavaScript applications!