What are they?
Typed arrays provide a way to quickly and easily manipulate the raw data stored inside a binary data buffer. This is really useful for processing audio and video data. They're similar to arrays, but with some subtle differences we'll cover in the How are they different from normal arrays? section.
How do they work?
To get an understanding of typed arrays, let's look at the following areas:
- Numeric data types - a way of representing the data stored in an array buffer
- Array Buffers – where the data is stored
- Data Views – reading and writing the data in a typed array
Numeric data types
Numbers are stored in a 64-bit floating point format in JavaScript, which isn't particularly efficient if you only need to represent an 8-bit integer (you're wasting 56 bits!).
Numeric types give us the ability to allocate only the memory we need, which makes mathematical operations on the
data a lot more speedy. For example, if you use an int8
typed array, then each element in the
array will take up 8 bits.
The following 8 numeric types are available:
- int8
- uint8
- int16
- uint16
- int32
- uint32
- float32
- float64
Array Buffers
An array buffer is an object that represents the raw binary data of the typed array. Their contents can't be manipulated directly, so to do so you'll need to make use of a data view.
let arrayBuffer = new ArrayBuffer(5); // allocates 5 bytes for this buffer
Data Views
Data views are the means by which the data stored in an array buffer can be accessed and manipulated.
There are type specific views for each of the different numeric types and also a generic DataView
object.
let arrayBuffer = new ArrayBuffer(10); // allocates 10 bytes for this buffer
// creates a generic Data View object with access to all 10 bytes
let dataView = new DataView(arrayBuffer);
dataView.setInt8(0, 5); // stores the number 5 in the first byte
dataView.getInt8(0); // returns the number 5
// be careful here – we assigned an int8 to the first location, but we
// can ask for an int16
// (byte 1) 00000101 (byte 2 ) 00000000 together they make 0000010100000000
// (or 1280 in base 10)
dataView.getInt16(0); // 1280
As you can see in the above example, with a generic data view object you can access the data in any of the available formats. If this is not what you want, then use the type-specific data views.
let arrayBuffer = new ArrayBuffer(10); // allocates 10 bytes for this buffer
// access to 6 8-bit ints starting from the 1st byte (index 0)
let int8Array = new Int8Array(arrayBuffer, 0, 6);
// access to 2 16-bit ints starting from the 7th byte (index 6)
let int16Array = new Int16Array(arrayBuffer, 6, 2)
int8Array.length; // 6
int16Array.length; // 2
int8Array[0] = 127;
int8Array[0]; // 127
// assigning a number larger than can be represented with a signed byte
int8Array[1] = 128;
// binary overflow means the number flips around to -128
// 128 is 10000000 in binary and since we are using signed
// integers the first bit (1) indicates this is a negative
// number. The maximum positive number we can store
// is 01111111 (127)
int8Array[1]; // -128
int16Array[0] = 128;
int16Array[0]; // 128 – no binary overflow here!
Note: with the unsigned int arrays (Uint8Array
, Uint16Array
, Uint32Array
) any value below 0 will loop back
around to the maximum value available and any value above the maximum value will loop back around to 0. However,
there is a special Uint8ClampedArray
for unsigned 8-bit integers. In this case, any value below 0
will be capped at 0 and any value above 255 will be capped at 255.
How are they different from normal arrays?
- Typed arrays aren't
Array
s– they don't inherit fromArray
Array.isArray(new Int8Array()); // false
- A typed array's size can't be altered once it's been created. Any attempt at setting a value at a non-existent index will be ignored:
let int8Array = Int8Array.of(1, 2, 3);
int8Array[5] = 10;
int8Array; // Int8Array [ 1, 2, 3 ]
- The following methods are not available for typed arrays as they could result in a typed array that has a
different size:
concat
shift
pop
splice
push
unshift
- The
set
andsubarray
methods are available on typed arrays, but not on normal arrays.set
is used for setting multiple values in a typed array, andsubarray
is used for extracting a new typed array containing some of the elements of another typed array.
let ints = new Int8Array(4);
ints.set([2,3]); // sets the first element to 2 and the second to 3
// 2 is used as an offset index. The 3rd element is set to 5 and the
// 4th element is set to 8
ints.set([5, 8], 2);
ints; // Int8Array [ 2, 3, 5, 8 ]
let moreInts = Int8Array.of(1, 3, 5, 8, 13);
let clone = moreInts.subarray(); // Int8Array [ 1, 3, 5, 8, 13 ]
clone === moreInts; // false - subarray() creates a new typed array
moreInts.subarray(2); // Int8Array [ 5, 8, 13] – 2 is used as the offset index
moreInts.subarray(2, 3); // Int8Array [ 5 ] – the end index is exclusive
Where can I learn more?
- Understanding ECMAScript 6 is my favourite book right now. Give it a read.
- I'm making notes as I go through the book. Nicholas was kind enough to let me make these public, so you can follow along here.
- The MDN web docs
- The ECMAScript specification