Javascript typed arrays



JavaScript arrays are one of the most fundamental data structures used to solve different problems. The majority of different programming languages provide the array functionality to hold similar kinds of data elements successively. The web programming language JavaScript also allows using arrays inside it. JavaScript also supports another interesting feature, called Typed Arrays. The typed arrays are like normal arrays but it provides the functionality to read and write raw binary data in memory buffers.

Why do we need Typed Arrays?

Like other programming languages, JavaScript supports Array objects which can store values and objects inside them. These arrays are dynamic so that they can grow and shrink whenever needed. For web programming, JavaScript optimizes the source code and the engine performs array access much faster. But in the normal array, it can store any kind of data, and in web technology, the data variations are much more versatile. Sometimes they can be images, video audio, and some other object types. But sometimes we may need to access the raw binary data directly from the memory. In that aspect, the typed array comes into the picture. Each element in a JavaScript Typed-array is raw binary data. There is a variety of different supported data formats. From 8-bit integers to 64-bit floating-point numbers and much more.

Components of Typed Arrays: Buffers and Views

The typed arrays in JavaScript have some components which enable the total flexibility of using typed array features. It mainly has two different components. The first one is the Buffers and the second one is Views. Buffers can be implemented using the ArrayBuffer object in JavaScript. This object represents the chunk of data. And to read, write and manipulate the data, we need to use a view. The view is like a window. From different sized views (like a different sized window) we can see different sizes of the byte components from the ArrayBuffer. This view provides a context where the data type, starting offset, index management, and the number of elements can be utilized. Thus, the entire array-like object can be formed. See the following figure to understand the concept of ArrayBuffer and different views on the same.

ArrayBuffer in JavaScript

ArrayBuffer datatype creates a generic fixed-length binary data buffer. To create an ArrayBuffer we need to provide the number of bytes we want to assign. The syntax is fairly simple −

Syntax

buffer = new ArrayBuffer(<number of bytes>)

DataView in JavaScript

DataView enables full control over the typed array in JavaScript. There are several types of views like Int8Array− for 8-bit signed integer numbers. Uint8Array− for 8-bit unsigned numbers. Float64Array− For 64-bit IEEE floating-point numbers, etc. These DataView provide a low-level interface to enable getter/setter API to read and write arbitrary data to the ArrayBuffer. Creating a view is also simple. Follow the syntax for better understanding−

Syntax

view1 = new ViewType(<array buffer object>);
view2 = new ViewType(<array buffer object>);

The ViewType could be anything like Float64Array, Int32Array, etc.

Examples

Define a simple ArrayBuffer with the size of 16 bytes, and print its size.

Source Code

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3>Output Console</h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const buffer = new ArrayBuffer(16); content += "Size of buffer: " + buffer.byteLength } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

Create one Int32Array view to store 32-bit integer numbers. And store first few squared numbers in it

Source Code

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const buffer = new ArrayBuffer(16); const int32View = new Int32Array(buffer); for (let i = 0; i < int32View.length; i++) { int32View[i] = i * i; } content += "The int32View Buffer: " + int32View } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

Why there are only four integers have generated? This is because we have created a 32-bit integer array so each integer is taking 32-bit space (4 bytes). And our buffer is 16 bytes. So 16/4 = 4 integers are generated.

We can use multiple views for the same ArrayBuffer. In the following example, we are creating another view for 16-bit integers for the same array buffer.

Source Code

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const buffer = new ArrayBuffer(16); const int32View = new Int32Array(buffer); const int16View = new Int16Array(buffer); for (let i = 0; i < int32View.length; i++) { int32View[i] = i * i; } content += "The int32View Buffer: " + int32View + '<br>' content += "The int16View Buffer: " + int16View + '<br>' } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

The output shows for the 16-bit integers, it is creating 8 numbers for the same buffer. But we can see some numbers are 0’s in between. The reason behind this is simple. For example, the number 9 in Int32Array is 9 itself, but in Int16Array it turns into (0, 9) this is because in the first case the 9 is represented as a 32-bit number where the least significant 4 bits are representing 9 (1001). But in the next case, these 32 bits are split into two 16-bit numbers and the most significant 16 bits is now a different number. In this case, it turns into 0

We can use multiple views for the same ArrayBuffer. In the following example, we are creating another view for 16-bit integers for the same array buffer.In the next example, we can see if we update the value of an element present in the typed array from one view, from the other view it will also get updated.

Source Code

<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3> Output Console </h3> <p> Output: </p> <div id="output"> </div> <div id="opError" style="color : #ff0000"> </div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { const buffer = new ArrayBuffer(16); const int32View = new Int32Array(buffer); const int16View = new Int16Array(buffer); for (let i = 0; i < int32View.length; i++) { int32View[i] = i * i; } content += 'Before<br>' content += "The int32View Buffer: " + int32View + '<br>' content += "The int16View Buffer: " + int16View + '<br>' int16View[0] = 50; content += '<br>After<br>' content += "The int32View Buffer: " + int32View + '<br>' content += "The int16View Buffer: " + int16View + '<br>' } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>

Conclusion

The typed array is very much similar to the normal array objects in JavaScript. In this approach, we can directly access the raw binary data from the memory. There are two different components present in the Typed array concept. The first one is the actual buffer object of a given size (in bytes) and the second one is the view. A single buffer may have multiple views. And these views have different data types, sizes, and other parameters associated with them to make the buffer used as a normal array object.


Advertisements