Uint16Array: примеры (JAVASCRIPT)

Использование Uint16Array для манипуляции данными
Раздел: Бинарные данные, Типизированные массивы
Uint16Array(buffer: ArrayBuffer | length: number | array: Iterable | object): Uint16Array

Основа Uint16Array

Uint16Array — это типизированный массив, представляющий собой представление бинарных данных в виде 16-битных беззнаковых целых чисел в порядке байтов платформы. Он является частью семейства TypedArray и используется для работы с бинарными данными, например, при обработке аудио, видео, файлов или сетевых протоколов.

Конструктор может быть вызван несколькими способами:

  • new Uint16Array(): Создает пустой массив.
  • new Uint16Array(length): Создает массив с заданным количеством элементов, каждый инициализируется нулем.
  • new Uint16Array(typedArray): Создает массив на основе другого типизированного массива (копирует данные).
  • new Uint16Array(object): Создает массив из итерируемого объекта (например, обычного массива).
  • new Uint16Array(buffer [, byteOffset [, length]]): Создает представление для существующего ArrayBuffer.

Методы и свойства аналогичны обычным массивам (map, filter, slice, length, индексы), но элементы ограничены диапазоном от 0 до 65535. При выходе за диапазон значение оборачивается (присваивается значение & value % 65536).

Основные примеры применения

Создание массива заданной длины:

let arr1 = new Uint16Array(3);
console.log(arr1);
Uint16Array(3) [ 0, 0, 0 ]

Создание из обычного массива:

let arr2 = new Uint16Array([1000, 2000, 65535]);
console.log(arr2);
Uint16Array(3) [ 1000, 2000, 65535 ]

Создание представления ArrayBuffer:

let buffer = new ArrayBuffer(8);
let arr3 = new Uint16Array(buffer);
let arr4 = new Uint16Array(buffer, 2, 2);
console.log(arr3.length, arr4.length);
4 2

Похожие типизированные массивы в JavaScript

В JavaScript существуют и другие типизированные массивы для работы с целыми и вещественными числами разной разрядности:

  • Int16Array: 16-битные целые числа со знаком (-32768 до 32767).
  • Uint8Array / Int8Array: 8-битные числа, часто используются для работы с байтами.
  • Uint32Array / Int32Array: 32-битные числа для более широкого диапазона значений.
  • Float32Array / Float64Array: Для чисел с плавающей точкой.

Uint16Array часто применяется для работы с 16-битными данными, например, при декодировании аудио (частота дискретизации), обработке 16-битных цветов (RGB565) или данных из бинарных протоколов.

Типичные ошибки при использовании

Ошибка при передаче отрицательных чисел (значение оборачивается):

let arr = new Uint16Array([-1]);
console.log(arr[0]);
65535

Ошибка при передаче числа больше 65535 (оборачивание):

let arr = new Uint16Array([65536]);
console.log(arr[0]);
0

Попытка изменить размер после создания:

let arr = new Uint16Array(2);
arr.length = 5;
console.log(arr.length);
2 // Длина неизменна

Ошибка доступа к несуществующему индексу:

let arr = new Uint16Array(2);
console.log(arr[10]);
undefined

Изменения в последних версиях

Uint16Array как часть спецификации TypedArray стабилен уже долгое время. Основные изменения касаются добавления новых методов, общих для всех типизированных массивов, в соответствии со стандартом ES2015 и более поздними. Например, добавлены методы .from(), .of(), .copyWithin(), .find(), .includes(). Также улучшена интеграция с другими API, такими как WebGL, Web Audio API и Streams.

В современных браузерах и средах выполнения (Node.js) производительность работы с TypedArrays была значительно оптимизирована.

Расширенные примеры использования

Обработка данных изображения в формате RGB565 (16 бит на пиксель):

Пример javascript
// Предположим, что у нас есть массив пикселей в формате RGB565
let pixelData = new Uint16Array([0xF800, 0x07E0, 0x001F]); // Красный, Зеленый, Синий
function decodeRGB565(value) {
    let r = (value & 0xF800) >> 11;
    let g = (value & 0x07E0) >> 5;
    let b = (value & 0x001F);
    return { r, g, b };
}
pixelData.forEach(pixel => console.log(decodeRGB565(pixel)));
{ r: 31, g: 0, b: 0 }
{ r: 0, g: 63, b: 0 }
{ r: 0, g: 0, b: 31 }

Создание и использование DataView совместно с Uint16Array для контроля порядка байтов:

Пример javascript
let buffer = new ArrayBuffer(4);
let view = new DataView(buffer);
view.setUint16(0, 0x1234, true); // little-endian
let arr = new Uint16Array(buffer);
console.log(arr[0].toString(16));
1234 // В порядке байтов платформы

Использование в WebGL для передачи данных вершин:

Пример javascript
// Упрощенный пример
let gl = canvas.getContext('webgl');
let indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
let indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

Арифметические операции с использованием .map (с учетом оборачивания значений):

Пример javascript
let data = new Uint16Array([100, 200, 300]);
let doubled = data.map(x => x * 2);
console.log(doubled);
Uint16Array(3) [ 200, 400, 600 ]

Создание подмассива без копирования данных (представление):

Пример javascript
let mainArray = new Uint16Array([10, 20, 30, 40, 50]);
let subView = new Uint16Array(mainArray.buffer, 2*2, 2); // 2 элемента, начиная с байта 4
console.log(subView);
mainArray[2] = 999;
console.log(subView); // Изменения видны
Uint16Array(2) [ 30, 40 ]
Uint16Array(2) [ 999, 40 ]

Аналоги в других языках программирования

Концепция типизированных массивов или массивов фиксированного типа существует во многих языках.

Python (модуль array):

import array
arr = array.array('H', [1000, 2000, 65535])
print(arr)
array('H', [1000, 2000, 65535])

C (массив определенного типа):

#include <stdio.h>
int main() {
    unsigned short arr[3] = {1000, 2000, 65535};
    printf("%hu, %hu, %hu", arr[0], arr[1], arr[2]);
    return 0;
}
1000, 2000, 65535

PHP (пакет pack/unpack):

$data = pack('S*', 1000, 2000, 65535);
$unpacked = unpack('S*', $data);
print_r($unpacked);
Array ( [1] => 1000 [2] => 2000 [3] => 65535 )

Отличия от JavaScript часто заключаются в необходимости явного указания порядка байтов (endianness) при сериализации.

JS Uint16Array function comments

En
Uint16Array Represents an array of 16-bit unsigned integers.