Back to Home

ArrayBuffer, binary arrays

In web-development we meet binary data mostly while dealing with files (create, upload, download). Another typical use case is image processing. That’s all possible in JavaScript, and binary operations are high-performant. Although, there’s a bit of confusion, because there are many classes. To name a few: - ArrayBuffer, Uint8Array, DataView, Blob, File, etc. Binary data in JavaScript is implemented in a non-standard way, compared to other languages. But when we sort things out, everything becomes fairly simple. The basic binary object is ArrayBuffer – a reference to a fixed-length contiguous memory area. We create it like this: This allocates a contiguous memory area of 16 bytes and pre-fills it with zeroes. ArrayBuffer is a memory area. What’s stored in it? It has no clue. Just a raw sequence of bytes. To manipulate an ArrayBuffer, we need to use a “view” object. A view object does not store anything on its own. It’s the “eyeglasses” that give an interpretation of the bytes stored in the ArrayBuffer. For instance: - Uint8Array – treats each byte in ArrayBuffer as a separate number, with possible values from 0 to 255 (a byte is 8-bit, so it can hold only that much). Such value is called a “8-bit unsigned integer”. - Uint16Array – treats every 2 bytes as an integer, with possible values from 0 to 65535. That’s called a “16-bit unsigned integer”. - Uint32Array – treats every 4 bytes as an integer, with possible values from 0 to 4294967295. That’s called a “32-bit unsigned integer”. - Float64Array – treats every 8 bytes as a floating point number with possible values from 5.0x10-324 to 1.8x10308. So, the binary data in an ArrayBuffer of 16 bytes can be interpreted as 16 “tiny numbers”, or 8 bigger numbers (2 bytes each), or 4 even bigger (4 bytes each), or 2 floating-point values with high precision (8 bytes each). ArrayBuffer is the core object, the root of everything, the raw binary data. But if we’re going to write into it, or iterate over it, basically for almost any operation – we must use a view, e.g:

TypedArray

The common term for all these views (Uint8Array, Uint32Array, etc) is TypedArray. They share the same set of methods and properties. Please note, there’s no constructor called TypedArray, it’s just a common “umbrella” term to represent one of views over ArrayBuffer: Int8Array, Uint8Array and so on, the full list will soon follow. When you see something like new TypedArray, it means any of new Int8Array, new Uint8Array, etc. Typed arrays behave like regular arrays: have indexes and are iterable. A typed array constructor (be it Int8Array or Float64Array, doesn’t matter) behaves differently depending on argument types. There are 5 variants of arguments: 1. If an ArrayBuffer argument is supplied, the view is created over it. We used that syntax already. Optionally we can provide byteOffset to start from (0 by default) and the length (till the end of the buffer by default), then the view will cover only a part of the buffer. 2. If an Array, or any array-like object is given, it creates a typed array of the same length and copies the content. We can use it to pre-fill the array with the data:

let arr = new Uint8Array([0, 1, 2, 3]);
alert( arr.length ); // 4, created binary array of the same length
alert( arr[1] ); // 1, filled with 4 bytes (unsigned 8-bit integers) with given values
  1. If another TypedArray is supplied, it does the same: creates a typed array of the same length and copies values. Values are converted to the new type in the process, if needed.
let arr16 = new Uint16Array([1, 1000]);
let arr8 = new Uint8Array(arr16);
alert( arr8[0] ); // 1
alert( arr8[1] ); // 232, tried to copy 1000, but can't fit 1000 into 8 bits (explanations below)
  1. For a numeric argument length – creates the typed array to contain that many elements. Its byte length will be length multiplied by the number of bytes in a single item TypedArray.BYTES_PER_ELEMENT:
let arr = new Uint16Array(4); // create typed array for 4 integers
alert( Uint16Array.BYTES_PER_ELEMENT ); // 2 bytes per integer
alert( arr.byteLength ); // 8 (size in bytes)
  1. Without arguments, creates an zero-length typed array. We can create a TypedArray directly, without mentioning ArrayBuffer. But a view cannot exist without an underlying ArrayBuffer, so gets created automatically in all these cases except the first one (when provided). To access the underlying ArrayBuffer, there are following properties in TypedArray:
let buffer = new ArrayBuffer(16); // create a buffer of length 16
alert(buffer.byteLength); // 16
Example:

Follow the lesson from Microsoft Web-Dev-For-Beginners course

Tags: array