JavaScript Data Structures - Typed Arrays I
Written by Ian Elliot   
Tuesday, 23 July 2013
Article Index
JavaScript Data Structures - Typed Arrays I
ArrayBuffer

JavaScript's typed arrays are relatively new, but they bring a way to work with binary data and to work with structures that would otherwise be very difficult. In this first article we look at the basic idea of using typed arrays - views, BufferArray and block operations.

This is part one of a three part series on typed arrays:

 

 

It is also is part of a larger series on implementing data structures in JavaScript. The other articles are:

 

 

JavaScript is a lightly typed language, and this is how most users like it, but there are times when you need to work with data that has specific representations. For example, you might need to read in and work with a byte array. Here it isn't only the case that each array element should behave like a byte data type, i.e. be limited to 0 to 255, but it is also important that it is stored using a single byte of memory and the array should be a contiguous area of memory treated as a sequence of bytes. In such a situation it isn't clear that is really is a case of data typing, but more a way of getting back to the underlying representations of the data.

To make the point clearer - anything you can store in a typed array can be stored in a standard JavaScript Array object. In this sense you get nothing new apart from the guarantee of a particular layout in memory and the representation used.  

Typed arrays were introduced in JavaScript to allow it to work with OpenGL as part of the implementation of WebGL. While previously you could arrange to convert a JavaScript Array into whatever the API needed - a byte array say - this proved to be too slow. Typed arrays allowed the data to be constructed in JavaScript in a format that could be consumed without conversion by the API.

Since then typed arrays have become a way of working with external frameworks of all kind and a way of accessing binary data directly. Before typed arrays the standard way of working with binary data was to store it as a string and convert each character to and from its representation as an integer. Typed arrays make binary data much easier to work with.

There is also the issue of efficiency. Typed arrays allow the JavaScript engine to perform some optimizations, but these depend on the engine and are a matter of some ongoing debate. This article focuses on the way typed arrays allow us to work with binary data rather then matters of efficiency.

The only major problem with typed arrays is that they aren't universally supported. The latest browsers all support it, with IE10 doing some things slightly differently. Older browsers tend not to support it - with IE9 and earlier being the biggest problems. 

So if you plan to use typed arrays you need to make sure that you tell users to upgrade to the latest browser if your program doesn't work. 

Basic Typed Arrays

The way that typed arrays work is very simple and very powerful and very similar to the way that arrays work in C.

Creating a typed array is just a matter of using the array's constructor. For example:

var bytes=new Uint8Array(10);
bytes[0]=0xFF;
bytes[9]=0xFF;
console.log(bytes[0]);

This creates an array of 10 unsigned 8-bit types. Notice that once created you can use the array as normal, but it doesn't have all of the methods that the Array object does. In this case the array elements are single bytes representing 0 to 255. All typed arrays are initialized to zero when created. 

Notice that the array is allocated enough memory to hold all of the elements when it is first constructed. For example:

var Ints=new Uint16Array(10);

creates an array of 16-bit unsigned integers and hence allocates 20 bytes of memory to store the entire array.

Using any of the typed arrays follows the same pattern and all you really have to know extra is what is available:

 

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

 

 

Notice that we have types for one, two and four byte integer values both signed and unsigned and a four and eight byte float.

The only type that might need further explanation is the Uint8ClampedArray.  A byte variable has a very small range 0 t0 255 and usually overflow is a problem. There are generally two ways to deal with this either roll over after 255 to 0 or use saturation arithmetic which clamps the value to 255. In other words, Uint8ClampedArray doesn't allow a value bigger than 255 and

clamped[0]=255+1

is 255. 

IE10 doesn't support clamped arrays.

Notice also that for the unclamped array types the alternative strategy is taken and the value rolls over. For example: 

bytes[0]=255+1;

is zero. It also rolls over if you try to assign a value that is too large. 

So rollover is the rule for all typed arrays except for clamped.

 

Banner

Operators

If you create an array of a given type then the data stored is of that type. However, the arithmetic and other operators that you might apply to an array element perform the usual JavaScript operations after type conversion.

This is very reasonable, but it can also be confusing. For example, what would you expect the result of 

bytes[0]=0xFF; 
console.log(~bytes[0]);

to be?

The "~" is a bitwise not (see JavaScript Bit Manipulation is you have forgotten how it works) and so the byte 11111111 should be converted into 00000000 and the result should be zero. However it is actually -256. 

 

How can this be? 

The answer is that all JavaScript bitwise operations work with a 16-bit integer and so the value that the not operates on is 

0000000011111111

and when you apply the bitwise not you get

1111111100000000

which is then treated as a 16-bit signed integer and converted to a standard 64-bit float before being printed, which gives the -256. 

Notice that in this case the high order bits are lost if you assign the operation back to an array element of type Uint8Array. That is:

bytes[0]=0xFF;
bytes[0]=~bytes[0] 
console.log(bytes[0]);

does give the expected result of zero, but only because the 16-bit result is truncated to 8-bits by the type conversion. 

The same is true of arithmetic when the value stored in the array will be converted into a 64-bit float. Notice that none of the integer nor floating point array types will lose precision in this conversion. What non-JavaScript frameworks that you pass a typed array to do with the values is another matter and you just have to investigate on a case-by-case basis. 

<ASIN:0596517742>
<ASIN:0596805527>
<ASIN:0470684143>



Last Updated ( Tuesday, 20 August 2013 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.