ES6 Everyday: Typed Arrays

“Typed arrays” provide an efficient method for accessing and manipulating data. The motivation behind this is to provide a construct to handle all of the raw binary data that will start flowing into JavaScript (audio data, video data, etc.).

“Typed arrays” actually encompasses two separate classes: ArrayBuffer and DataView.

The ArrayBuffer contains our data and the DataView provides a custom view into this data.

First, let’s create a buffer 8 bytes long:

var buffer = new ArrayBuffer(8);
console.log(buffer.byteLength); // 8

Now let’s create a DataView to manipulate the data within our buffer:

var buffer = new ArrayBuffer(8);

var view = new DataView(buffer);
view.setInt8(0, 3);

console.log(view.getInt8(0)); // 3

You’ll notice here that we were pretty specific: we used setInt8 to put the value “3” in the 0-byte offset position of the ArrayBuffer.

Let’s try something:

var buffer = new ArrayBuffer(8);

var view = new DataView(buffer);
view.setInt32(0, 3);

console.log(view.getInt8(0)); // 0
console.log(view.getInt8(1)); // 0
console.log(view.getInt8(2)); // 0
console.log(view.getInt8(3)); // 3

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

In this example, we stashed the value into our ArrayBuffer using setInt32. Since setInt32 takes up 4 bytes (32 bits = 4 bytes), rather than 1 byte like setInt8 (8 bits = 1 byte), our getInt8 calls don’t find the number until our offset is 4 bytes into the buffer.

Rather than creating a generic DataView, there are typed array view classes with more specific names that we can create and access like regular arrays:

var buffer = new ArrayBuffer(8);

// 32-bit View
var bigView = new Int32Array(buffer);
bigView[0] = 98;
bigView[1] = 128;

for(let value of bigView)
{
  console.log(value);
  // 98
  // 128
}


// 16-bit View
var mediumView = new Int16Array(buffer);

for(let value of mediumView)
{
  console.log(value);
  // 98
  // 0
  // 128
  // 0
}

// 8-bit View
var smallView = new Int8Array(buffer);

for(let value of smallView)
{
  console.log(value);
  // 98
  // 0
  // 0
  // 0
  // -128
  // 0
  // 0
  // 0
}


// 8-bit Unsigned View
var unsignedView = new Uint8Array(buffer);

for(let value of unsignedView)
{
  console.log(value);
  // 98
  // 0
  // 0
  // 0
  // 128
  // 0
  // 0
  // 0
}

The example above shows how you can have several different views looking into the same ArrayBuffer.

You’ll also notice in our third example (using Int8Array), our value of “128” gets flipped to a negative value. This is because our 8-bit view can’t handle a number this large since it takes 8-bits to represent “128” in binary (0b10000000) and the extra bit is reserved for a sign. As a result, overflow occurs and we get kicked to “-128”.

However, when we use Uint8Array, the unsigned version of Int8Array, we no longer care about the sign so we get a little extra room to properly represent our value.

Resources