Работа с типизированными массивами и буферами в JavaScript

Теория
Что такое буфер? Буфер это массив для хранения сырых данных в с определённой длиной в n байтов. Буфер невозможно изменять, для это нужен другой объект, представляющий эти данные. Этот объект нужен для записи и изменения данных буфера, не трогая сам буфер.
Для создания буферов есть ArrayBuffer, а для отображения данных используются либо типовые массивы, либо DataView. И у обоих можно устанавливать ячейки.
buf = new ArrayBuffer(16) // byteLength: 16 view = new DataView(buf) // buffer: ArrayBuffer view.setFloat64(0, 20.4) view.getFloat64(0) // 20.4 view.setInt16(0, 500) view.getInt16(0) // 500 view.getFloat64(0) // 3.046172450794506e-299
Можно заметить одну странность, мы просматриваем ячейку в формате Int16 как Float64. В DataView можно ставить один тип данных ячейку, а просматривать как другой.

Таблица типовых массивов
Ранее я упомянул типовые массивы. В отличие от DataView здесь нельзя менять тип данных. И он выглядит как обычный массив. Причём каждый тип данных по-своему распределяет буффер.
b = new ArrayBuffer(64); new Uint16Array(b) // Uint16Array(32) [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ] new Uint32Array(b) // Uint32Array(16) [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ] new Uint8Array(b) // Uint8Array(64) [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, … ]
У типовых массивов работают те же методы, что и у обычных, за исключением того что нельзя добавлять новые ячейки, потому что буффер неизменяем.
b = new ArrayBuffer(64) u = new Uint16Array(b) u.fill(2) // Uint16Array(32) [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, … ] u.slice(0,20) // Uint16Array(20) [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, … ]
Также у типовых массивов и DataView есть свойство byteOffset, с помощью которого можно его расширить:
b = new ArrayBuffer(64); u = new Uint16Array(b, 16) // смещение на 16 байтов console.log(u.length) // 24
Практика
Буфера используются в веб API, вот несколько из них:
XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open('GET', someUrl);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
const arrayBuffer = xhr.response;
···
};
xhr.send();
Fetch API
fetch(url) .then(request => request.arrayBuffer()) .then(arrayBuffer => ···);