> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b5-collections/04-typed-arrays.md).

# 04. Typed Arrays

Типизированные массивы в ES6 используются для работы с бинарными данными, а так же для взаимодействия с нативными API, использующими бинарные данные. С развитием веба появилось все больше API, работающих с бинарными данными.

* File API
* XMLHttpRequest
* Fetch API
* Canvas
* WebSockets
* WebGL
* Аудио/Видео

В Typed Array API используется две разновидности объектов:

* Типизированные массивы (`Uint8Array`, `Int16Array`, `Float32Array`, etc.) интерпретируют содержимое `ArrayBuffer` как индексированную последовательность элементов заданного типа.
* Объекты `DataView` позволяют получать доступ к содержимому `ArrayBuffer` как к элементам одного из числовых типов (`Uint8`, `Int16`, `Float32`, etc.) с определенной размерностью.

`ArrayBuffers` store the data, views (Typed Arrays and `DataView`) let you read and change it. In order to create a `DataView`, you need to provide its constructor with an `ArrayBuffer`. Typed Array constructors can optionally create an `ArrayBuffer` for you.

## `ArrayBuffer`

Объект `ArrayBuffer` это стандартный набор бинарных данных с фиксированной длинной. Вы не можете манипулировать содержимым `ArrayBuffer` напрямую. Вместо этого, необходимо создать типизованное представление `DataView`, которое будет отображать буфер в определенном формате, и даст доступ на запись и чтение его содержимого.

```javascript
// 16 bytes array buffer
const buffer = new ArrayBuffer(16);

// we can have multiple views on the top of buffer
const int32View = new Int32Array(buffer);
const int16View = new Int16Array(buffer);
```

## Setting up Typed Array.

При создании типизированного массива вызывается его конструктор в котором указывается число байт:

```javascript
// Typed array views work pretty much like normal arrays.
var f64a = new Float64Array(8);
f64a[0] = 10;
f64a[1] = 20;
f64a[2] = f64a[0] + f64a[1];
```

Статический метод `ArrayBuffer.isView(obj)` принимает на вход `obj` в проверяет, является ли он `ArrayBuffer` или его представлением.

Если необходимо создать Typed Array из набора значений, то стоит использовать функцию `TypedArray.of(...items)`, играющей роль статического конструктора.

```javascript
Float32Array.of(0.151, -8, 3.7);
```

Аналогично массивам, существует метод `TypedArray<U>.from(source : Iterable<T>, mapfn? : T => U, thisArg?)` конвертирующий данные из итерируемого источника в новый объект типизированного массива

```javascript
const ui16 = Uint16Array.from(Uint8Array.of(0, 1, 2));
```

## Typed Arrays and regular Arrays

Типизированные массивы хоть и берут многое от массивов, технически ими не являются.

Сходства:

* У Typed Array есть поле `length`.
* Доступ к элементам Typed Array осуществляется по индексу в квадратных скобках `[...]`.
* У них есть все методы, свойственные массивам.
* Вызов `Arrays.isArray()` вернет `false` для типизированных массивов.
* Типизированные массивы являются итерируемыми.

Различия:

* Индекс элемента может быть отрицательным
* Все элементы типизированных массивов имеют один тип.
* Типизированные массивы являются непрерывными и не имеют дыр.
* Имеют поле `buffer`, ссылающееся на оригинальный буфер, представлением которого является данный типизированный массив.

## Byte Data

Типизированные массивы накладывают ограничения на значения своих элементов в диапазоне (в соответствии с типом). Для всех типизированных массивов, за исключением `UInt8ClampedArray` переполнение обрабатывается по обычным правилам:

* При переполнении в большую сторону, значение переходит в минимальное для данного диапазона
* При переполнении в меньшую сторону, значение переходит в большее для данного диапазона

```javascript
const uint8 = new Uint8Array(1);
uint8[0] = 255;
uint8[0]; // highest value within range
255;
uint8[0] = 256;
uint8[0]; // overflow
0;
```

Для `UInt8ClampedArray` выходящие за диапазон сбрасываются к своим соответствующим верхним/нижним границам.

Для типов данных, чья размерность превышает один байт начинает играть роль порядок байт. Для типизированных массивов используется порядок байт той платформы на которой они были созданы и не может быть измен в дальнейшем.

## `DataView`

Объект `DataView` это низкоуровневый интерфейс предоставляющий API для записи/чтения произвольных данных в буфер. Это полезно при работе с разнородными данными, например. В то время как типизованные представления всегда имеют порядок байт родной для вашей операционной системы, `DataView` позволяет контролировать порядок байт (byte-order). По умолчанию это`big-endian`, но через API можно установить `little-endian`.

Объекты `DataView` создаются при помощи следующего конструктора `DataView(buffer, byteOffset=0, byteLength=buffer.byteLength-byteOffset)` на основе существующего буфера.

Объекты `DataView` представляют read/write api для чтения данных из буфера. Два основных метода:

* `getElementType(byteOffset, littleEndian=false)` - читает данные в виде одного из типов.
* `setElementType(byteOffset, value, littleEndian=false)` - записывает данные в виде одного из типов.

  Где `ElementType` это один из `Float32`, `Float64`, `Int8`, `Int16`, `Int32`, `Uint8`, `Uint16`, `Uint32`

```javascript
const dv = new DataView(buffer);
const vector_length = dv.getUint8(0);
const width = dv.getUint16(1); // 0+uint8 = 1 bytes offset
const height = dv.getUint16(3); // 0+uint8+uint16 = 3 bytes offset
const vectors = new Float32Array(width * height * vector_length);
for (const i = 0, off = 5; i < vectors.length; i++, off += 4) {
  vectors[i] = dv.getFloat32(off);
}
```

Для объектов `DataView` можно контролировать порядок байт, указывая его в методах доступа/чтения. По умолчанию используется `BigEndian`.

Объекты `DataView` могут использоваться для гетерогенных данных.

## References

* [Typed Arrays: Binary Data in the Browser](https://www.html5rocks.com/en/tutorials/webgl/typed_arrays/)
