JavaScript typed arrays

Draft
This page is not complete.

As web applications become more and more powerful, adding features such as audio and video manipulation, access to raw data using WebSockets, and so forth, it has become clear that there are times when it would be helpful for JavaScript code to be able to quickly and easily manipulate raw binary data. In the past, this had to be simulated by treating the raw data as a string and using the charCodeAt() method to read the bytes from the data buffer.

However, this is slow and error-prone, due to the need for multiple conversions (especially if the binary data is not actually byte-format data, but, for example, 32-bit integers or floats).

JavaScript typed arrays provide a mechanism for accessing raw binary data much more efficiently.

Documentation

ArrayBuffer
The ArrayBuffer is a data type that is used to represent a generic, fixed-length binary data buffer. You can't directly manipulate the contents of an ArrayBuffer; instead, you create an ArrayBufferView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.
ArrayBufferView
The ArrayBufferView type describes a particular view on the contents of an ArrayBuffer's data. Of note is that you may create multiple views into the same buffer, each looking at the buffer's contents starting at a particular offset. This makes it possible to set up views of different data types to read the contents of a buffer based on the types of data at specific offsets into the buffer
DataView

The DataView view provides a low-level interface for reading data from and writing it to an ArrayBuffer.

StringView Non native
In this article is published a library of ours whose aims are:
  • creating a C-like interface for strings (i.e. array of characters codes — an ArrayBufferView in JavaScript) based upon the JavaScript ArrayBuffer interface,
  • creating an highly scalable library, that anyone can extend by adding methods to the object StringView.prototype,
  • creating a collection of methods for such string-like objects (since now: stringViews) which work strictly on arrays of numbers rather than on creating new immutable JavaScript strings,
  • working with other Unicode encodings different from default JavaScript's UTF-16 DOMStrings,
Getting ArrayBuffers or typed arrays from Base64-encoded strings
Code snippets to get ArrayBuffers or typed arrays from Base64-encoded strings.
FileReader.prototype.readAsArrayBuffer()
The FileReader.prototype.readAsArrayBuffer() method starts reading the contents of the specified Blob or File.
XMLHttpRequest.prototype.send()
XMLHttpRequest instances' send() method now supports typed arrays and ArrayBuffers as argument.

View All...

Community

Tools

View All...

Buffers and views: typed array architecture

To achieve maximum flexibility and efficiency, JavaScript typed arrays split the implementation into a buffer and a view. A buffer (implemented by the ArrayBuffer class) is an object representing a chunk of data; it has no format to speak of, and offers no mechanism for accessing its contents. In order to access the memory contained in a buffer, you need to use a view. A view provides a context—that is, a data type, starting offset, and number of elements—that turns the data into an actual typed array. Views are implemented by the ArrayBufferView class and its subclasses.

Typed array subclasses

The following subclasses provide buffer views allowing access to the data in specific data types. Note that the classes that work with more than one byte (e.g. Int16Array) use the platform byte order. If control over byte order is needed, use DataView instead.

Type Size Description Equivalent C type
Int8Array 1 8-bit twos complement signed integer signed char
Uint8Array 1 8-bit unsigned integer unsigned char
Uint8ClampedArray 1 8-bit unsigned integer unsigned char
Int16Array 2 16-bit twos complement signed integer short
Uint16Array 2 16-bit unsigned integer unsigned short
Int32Array 4 32-bit twos complement signed integer int
Uint32Array 4 32-bit unsigned integer unsigned int
Float32Array 4 32-bit IEEE floating point number float
Float64Array 8 64-bit IEEE floating point number double

Typed arrays superclasses

Type Description
DataView The DataView view provides a low-level interface for reading data from and writing it to an ArrayBuffer.
StringView Non native The StringView view provides a C-like interface for strings (i.e. array of characters codes — an ArrayBufferView in JavaScript) based upon the JavaScript ArrayBuffer interface,

Using views with buffers

Let's create a 16-byte buffer:

var buffer = new ArrayBuffer(16);

At this point, we have a chunk of memory whose bytes are all pre-initialized to 0. There's not a lot we can do with it, though. We can confirm that it is indeed 16 bytes long, and that's about it:

if (buffer.byteLength == 16) {
  alert("Yes, it's 16 bytes.");
} else {
  alert("Oh no, it's the wrong size!");
} 

Before we can really work with this buffer, we need to create a view. Let's create a view that treats the data in the buffer as an array of 32-bit signed integers:

var int32View = new Int32Array(buffer);

Now we can access the fields in the array just like a normal array:

for (var i=0; i<int32View.length; i++) {
  int32View[i] = i*2;
}

This fills out the 4 entries in the array (4 entries at 4 bytes each makes 16 total bytes) with the values 0, 2, 4, and 6.

Multiple views on the same data

Things start to get really interesting when you consider that you can create multiple views onto the same data. For example, given the code above, we can continue like this:

var int16View = new Int16Array(buffer);

for (var i=0; i<int16View.length; i++) {
  console.log("Entry " + i + ": " + int16View[i]);
}

Here we create a 16-bit integer view that shares the same buffer as the existing 32-bit view and we output all the values in the buffer as 16-bit integers. Now we get the output 0, 0, 2, 0, 4, 0, 6, 0.

You can go a step farther, though. Consider this:

int16View[0] = 32;
console.log("Entry 0 in the 32-bit array is now " + int32View[0]);

The output from this is "Entry 0 in the 32-bit array is now 32". In other words, the two arrays are indeed simply views on the same data buffer, treating it as different formats. You can do this with any view types.

Working with complex data structures

By combining a single buffer with multiple views of different types, starting at different offsets into the buffer, you can interact with data objects containing multiple data types. This lets you, for example, interact with complex data structures from WebGL, data files, or C structures you need to use while using js-ctypes.

Consider this C structure:

struct someStruct {
  unsigned long id;
  char username[16];
  float amountDue;
};

You can access a buffer containing data in this format like this:

var buffer = new ArrayBuffer(24);

// ... read the data into the buffer ...

var idView = new Uint32Array(buffer, 0, 1);
var usernameView = new Uint8Array(buffer, 4, 16);
var amountDueView = new Float32Array(buffer, 20, 1);

Then you can access, for example, the amount due with amountDueView[0].

Note: The data structure alignment in a C structure is platform-dependent. Take precautions and considerations for these padding differences.

Conversion to normal arrays

After processing a typed array, it is sometimes useful to convert it back to a normal array in order to benefit from the Array prototype. Following is a way to do that.

var typedArray = new Uint8Array( [ 1, 2, 3, 4 ] ),
    normalArray = Array.apply( [], typedArray );
normalArray.length === 4;
normalArray.constructor === Array;

Compatibility

Typed arrays are available in WebKit as well. Chrome 7 includes support for ArrayBuffer, Float32Array, Int16Array, and Uint8Array. Chrome 9 and Firefox 15 add support for DataView objects. Internet Explorer 10 supports all types except Uint8ClampedArray and ArrayBuffer.prototype.slice.

Specification

See also