The occurrence of typed arrays

Typed arrays are an API introduced in HTML5 that allows developers to manipulate binary data directly using JavaScript. Before typed arrays, there was no way to manipulate binary data directly through JavaScript, usually by manipulating data types in JavaScript that were converted to binary at runtime. This adds a transformation process, and although JavaScript does a lot of optimizations for data types to improve efficiency, there is still a difference in efficiency compared to directly manipulating binaries. The typed array follows.

use

So, what are the scenarios where typed arrays can be used?

  • Canvas image processing.
  • WebGL communicates with graphics cards.
  • File operations
  • Ajax response

How to use

So, if typed arrays are so important, what are you waiting for? Get to them.

Since we’re dealing directly with binary data, which is stored in a contiguous area of memory, we need to have that area of memory first.

We can create a memory region:

let buffer = new ArrayBuffer()
Copy the code

ArrayBuffer is a constructor that allows us to instantiate an ArrayBuffer, which can be understood as a contiguous area of memory. Since the parameter passed to our constructor is null, the generated buffer points to a memory length of zero bytes, which is meaningless.

Well, let’s create a meaningful memory area.

buffer = new ArrayBuffer(8)
Copy the code

We pass the parameter 8 to the ArrayBuffer, which means to ask the browser to create an 8 byte memory area for us.

Let’s see if this area of memory is 8 bytes long

console.log(buffer.byteLength);
Copy the code

The output is 8, so the browser didn’t deceive us.

We assume that all 8 bytes should be 0 because we did not assign a value to buffer. Let’s just be sure. Let’s look at the first byte:

console.log(buffer[0])
Copy the code

Output: undefined.

Yi? Why is undefined?

Buffer [0] = 0; buffer[0] = 0;

Ok, it looks like we’re looking at the contents of the buffer in the wrong way.

How do you view the contents of a buffer?

An array of view

Dang Dang Dang Dang, eight big gold – making its debut

  • Int8Array: an 8-bit signed integer containing 1 byte.
  • Uint8Array: an 8-bit unsigned integer of 1 byte length
  • Int16Array: a 16-bit signed integer of 2 bytes.
  • Uint16Array: 16-bit unsigned integer of 2 bytes length
  • Int32Array: a 32 – bit signed integer containing 4 bytes.
  • Uint32Array: a 32-bit unsigned integer of 4 bytes in length
  • Float32Array: a 32-bit floating point number containing 4 bytes.
  • Float64Array: specifies a 64-bit floating point number, containing eight bytes.

What magical powers do these eight king Kong have? We cannot read or write buffer data directly, but these eight data types act as Bridges between reading and writing buffer contents.

Again, we want to look at the buffer. Create a bridge to read and write the buffer:

let int8Array = new Int8Array(buffer);
Copy the code

We created a bridge to read and write the buffer using 8-bit signed integers. Now what’s the first part of the buffer?

console.log(int8Array[0]);
Copy the code

The value of each byte stored in the buffer is 0 by default.

Let’s see how to assign a buffer using Int8Array:

int8Array[0] = 30;
int8Array[1] = 41;

int8Array[2] = 52;
int8Array[3] = 63;

int8Array[4] = 74;
int8Array[5] = 85;

int8Array[6] = 86;
int8Array[7] = 97;
Copy the code

Because Int8Array is one byte long, it is the same as the unit of buffer, so we can assign a value to the specified buffer by index.

Easy, right? It’s as simple as that.

The other seven Kings are used in the same way as Int8Array, but they are different. Let’s look at the differences between them.

This time we’re going to use Int16Array, which is still the buffer, and we’re going to create a new bridge, which is still going to the buffer.

let int16Array = new Int16Array(buffer);
Copy the code

Int16Array [0] int16Array[0] Let’s output:

console.log(int16Array[0])
Copy the code

Why, 10526?

I don’t understand. All right, let’s figure out where 10526 came from.

Let’s look at the binary data in the buffer.

Since the Int16Array is two bytes, when we read and write data from it, an index represents data equal to two bytes in the buffer.

Int16Array [0] is composed of binary data of 30 and binary data of 41:00011110 (30) 00101001 (41).

Let’s calculate the binary decimal numbers in the order 30, 41.

ParseInt (1111000101001, 2) // Outputs 7721Copy the code

The calculated value is 7721, which is not consistent with our output, right?

This is where the concept of byte order comes in. On our personal notebooks, it’s usually little endian byte order. The little endian order in our example is the binary order of 41 and 30, so we had a problem with the binary order, so let’s do it in binary order of 41 and 30

ParseInt (10100100011110, 2) // Output 10526Copy the code

As you can see, the output is 10526, which is consistent with what we would get if we used int16Array[0] directly.

The above example shows that the data is not easy to understand when parsing the buffer by changing the data structure, so we must be careful.

Properties and Methods

Objects instantiated by typed arrays contain some useful properties and methods:

length

The length attribute returns the number of data members of a typed array.

byteLength

Returns the length of a typed array in bytes. Notice the difference with length. ByteLength = Length * Number of bytes occupied by each data

byteOffset

Returns the byte in the buffer where the typed array’s data starts.

buffer

Buffer for typed arrays.

set

Copy an array to copy data from one memory segment to another.

let a = new Uint8Array(12);
a[0] = 31;
a[1] = 32;
let b = new Uint8Array(12);
b.set(a);
Copy the code

What this means is that the contents of buffer a are copied into buffer B completely, which is much faster than assigning by index.

Of course, a set supports copying data from an index


let a = new Uint8Array(12);
a[0] = 31;
a[1] = 32;
let b = new Uint8Array(10);
b.set(a, 2);
Copy the code

The code above means that the data in a is copied from the third index position in B.

subarray

Subarray means to take a typed array, take the contents of its subarray, and return a new typed array.

let a = new Uint8Array(8);
a[2] = 1;
letB = a.s ubarray (2, 3); console.log(b.length); console.log(b.byteLength);Copy the code

The first parameter of subarray indicates the number of indexes in the source array to be intercepted, and the second parameter indicates the number of indexes to be intercepted.

The mixed view

It is important to note that when we initialize our array of types, we can specify a section of buffer. This means that we can specify multiple types for a section of buffer. We call this a mixed view.

let buffer = new Buffer(8);
letIdArray = new Int8Array(buffer, 0,2);let nameArray = new Int8Array(buffer, 2, 4);
let ageArray = new Int8Array(buffer, 6, 2);
Copy the code

We use a memory area to represent a person’s ID, name, and age. This structure is similar to the C struct.

We divide an 8-byte memory into three parts:

  • Byte 0 to byte 1 indicates the ID.
  • Bytes 2 to 5 indicate username.
  • Bytes 6 to 7 indicate age.

DataView

JavaScript also introduced another view, the DataView, which also serves the purpose of buffer operations, but DataView operations are more granular and can be set to either big-endian or small-endian.

The constructor for DataView:

DataView(ArrayBuffer object buffer, read from the first byte of the buffer, read length);Copy the code

Here’s an example:

let buffer = new ArrayBuffer(10);
let view = new DataView(buffer);

Copy the code

How do I read it?

So we’ve created our view, so how do we read it?

  • GetInt8 (index, order) : reads an 8-bit integer from the index byte.
  • GetUint8 (index, order) : Reads an unsigned 8-bit integer starting from the index byte.
  • GetInt16 (index, order) : reads 2 bytes from the first index byte and returns a 16-bit integer.
  • GetUint16 (index, order) : reads 2 bytes from the first index byte and returns an unsigned 16-bit integer.
  • GetInt32 (index, order) : reads 4 bytes from the index byte and returns a 32-bit integer.
  • GetUint32 (index, order) : reads 4 bytes from the index byte and returns an unsigned 32-bit integer.
  • GetFloat32 (index, order) : Reads four bytes from the index byte and returns a 32-bit floating-point number.
  • GetFloat64 (index, order) : Reads 8 bytes from the index byte and returns a 64-bit floating point number.

JavaScript provides 8 ways to read, the function is very simple, but also very easy to understand, here is not a sample, you can try it yourself.

The first byte is the index. The second byte allows us to set the byte order. True for reading in small endian order and false for reading in big endian order.

How to write?

DataView supports fine-grained reads as well as fine-grained writes:

  • SetInt8 (index, value, order) : an 8-bit integer whose value is value for 1 byte is written from the first byte of index.
  • SetUint8 (index, value, order) : an unsigned 8-bit integer whose value is value for one byte is written from the first byte of index.
  • SetInt16 (index, value, order) : a 16-bit integer whose value is value for two bytes is written from the first byte of index.
  • SetUint16 (index, value, order) : an unsigned 16-bit integer with the value of value for two bytes starting from the index byte.
  • SetInt32 (index, value, order) : a 32-bit integer with a value of 4 bytes starting from the first byte of index.
  • SetUint32 (index, value, order) : an unsigned 32-bit integer with the value of value for four bytes starting from the index byte.
  • SetFloat32 (index, value, order) : A 32-bit floating-point number whose value is value is written to four bytes starting from the index byte.
  • SetFloat64 (index, value, order) : A 64-bit floating-point number with a value of 8 bytes written from the first byte of index.

Order still means to set the byte order for writing, true for small endian and false for big endian. The default is False.

And it’s very easy to use, so you can practice it.

So far, this is the end of the way JavaScript manipulates binary. When you come across scenarios where you need to directly manipulate memory, you might as well use these two methods.

Your future self will thank you for your efforts today.