|Written by Ian Elliot|
|Thursday, 28 February 2019|
Page 2 of 3
This is very reasonable, but it can also be confusing. For example, what would you expect the result of
How can this be?
and when you apply the bitwise not you get
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:
does give the expected result of zero, but only because the 16-bit result is truncated to 8-bits by the type conversion.
In many cases you can simply use typed arrays as described above but sometimes you need to do more sophisticated things. Every typed array makes use of an ArrayBuffer object to store its data. This is simply the block of memory that the typed array allocates to store its data and it doesn't have methods that allow you to access the data. To access the data you need a typed array which provides a view into the ArrayBuffer object.
The reason for this two level approach is so that you can acquire data and only later determine how you want to treat it. It is even possible to use multiple views with a single ArrayBuffer so providing alternative interpretations of the data. Some API calls return an ArrayBuffer leaving it up to you how to set up a view to process the data.
Think of the ArrayBuffer as just being the data storage and the view as being how to interpret the data.
When you crate a typed array an ArrayBuffer object is automatically created big enough to store the array. You can retrieve a reference to the ArrayBuffer via the buffer property.
To associate a new view with an existing ArrayBuffer all you have to do is specify it within the constructor. For example:
In this case a 10 byte buffer is now viewed via unit16 as five 16-bit unsigned integers. You can see the advantages of this approach in that you can get to the individual high and low bytes of the 16-bit integer via the bytes array and the entire 16-bit integer via the unit16 array. This saves a lot of additional work that would be necessary if you needed to combine the high and low bytes as a special operation.
If you want to do a lot of this sort of view swapping then you can create an instance of the ArrayBuffer directly. For example,
creates a buffer with ten bytes initialized to zero and
creates an array of unsigned 8-bit integers using it. You can also set another view into the same buffer using something like
Notice that arrays that share the same ArrayBuffer really do share the same data. In our example if you store something in unit16 then you have modified what is stored in bytes and bytes which share the same location in the buffer.
You can also specify an offset and a length for a view which determines exactly which part of the ArrayBuffer it uses.
Specifies that the view starts in the ArrayBuffer at the sixth byte and creates just two 16-byte integers. In this case unint16 is the same storage location as bytes and bytes and unint16 is bytes and bytes.
You can see that things could become very complicated with views sharing overlapping and non-overlapping portions of the ArrayBuffer but in general things are usually kept simple.
|Last Updated ( Thursday, 28 February 2019 )|