JS об'єкт TypedArray


Вступ

Об'єкт TypedArray в JavaScript - це не просто ще один конструктор, це цілісна система для ефективної роботи з двійковими даними. Замість використання звичайних масивів, де кожен елемент може містити будь-який тип даних, TypedArray надає можливість працювати з масивами, в яких кожен елемент є фіксованого типу. Це забезпечує швидкий доступ та обробку елементів, а також більшу прогнозованість та стабільність роботи.

Приклад 1:

const numbers = new Int16Array(2);
numbers[0] = 42;
numbers[1] = 9000;
console.log(numbers.length);    // 2
console.log(numbers[0]);        // 42

У цьому прикладі ми створили типізований масив для 16-бітних цілих чисел і зберегли в ньому два числа. Важливо зазначити, що цей масив може містити лише цілі числа, і якщо спробувати зберегти значення поза діапазоном 16-бітного цілого числа, результат може бути непередбачуваним.

TypedArray може представляти собою різні типи масивів, включаючи масиви цілих чисел з різною кількістю біт (наприклад, Int8Array, Int16Array), масиви плаваючої точки (наприклад, Float32Array) та інші. Вибір конкретного типу залежить від ваших потреб і специфікації даних, з якими ви працюєте.

Приклад 2:

const floatNumbers = new Float32Array(3);
floatNumbers[0] = 1.5;
floatNumbers[1] = 2.5;
floatNumbers[2] = 3.5;
console.log(floatNumbers.length);  // 3
console.log(floatNumbers[1]);      // 2.5

Тут ми створюємо масив плаваючої точки розміром у три елементи. Кожен елемент цього масиву може зберігати число з плаваючою комою.

Загалом, TypedArray - це міцний інструмент для ефективної роботи з двійковими даними в JavaScript, що надає широкі можливості для оптимізації та контролю над вашими даними.

автор: Bond

Робота з пам'яттю через TypedArray

Одна з ключових особливостей TypedArray полягає в тому, як ця структура дозволяє працювати з пам'яттю. TypedArray інтенсивно користується ArrayBuffer - об'єктом, що представляє блок видаленої пам'яті.

Приклад 1:

const buffer = new ArrayBuffer(16);  // 16 байтів пам'яті
const int32View = new Int32Array(buffer);
console.log(int32View.length); // 4

У цьому прикладі ми створюємо блок пам'яті розміром у 16 байтів і пов'язуємо його з типізованим масивом для 32-бітних цілих чисел. Оскільки кожне 32-бітне число займає 4 байти, масив містить 4 елементи.

Коли ви створюєте TypedArray безпосередньо, JavaScript автоматично створює ArrayBuffer для зберігання даних. Але часто може виникнути потреба працювати безпосередньо з ArrayBuffer, наприклад, при отриманні двійкових даних з мережі або роботі з файлами.

Приклад 2:

const buffer = new ArrayBuffer(8);  // 8 байтів пам'яті
const view1 = new Int16Array(buffer);
const view2 = new Uint8Array(buffer, 2, 2);  // починаємо з 2 байту і беремо 2 елементи

view1[1] = 300;
console.log(view2[0]);   // 44
console.log(view2[1]);   // 1

Тут ми створили один блок пам'яті і створили два різних перегляди для цього блоку. Це демонструє, як можна розділити одну й ту ж область пам'яті між декількома TypedArray.

Важливо розуміти, що TypedArray - це лише "перегляд" або "інтерфейс" для доступу до даних в ArrayBuffer. Це означає, що коли ви змінюєте дані через один TypedArray, ці зміни відображаються на всіх інших TypedArray, які посилаються на той же ArrayBuffer.

Приклад 3:

const buffer = new ArrayBuffer(16);
const int16View = new Int16Array(buffer);
const int32View = new Int32Array(buffer, 4, 2);  // починаємо з 4-го байту

int16View[1] = 1000;
console.log(int32View[0]);  // 1000

Тут ми бачимо, як зміна значення в одному перегляді автоматично змінює дані в іншому перегляді, який посилається на ту ж саму область пам'яті.

Використовуючи TypedArray та ArrayBuffer, програмісти можуть більш ефективно керувати пам'яттю та оптимізувати обробку двійкових даних в JavaScript.

автор: Bond

Зміна розміру та відстеження довжини

Коли ви працюєте з TypedArray, важливо розуміти, як вони реагують на зміни розміру відповідних ArrayBuffer. Це особливо актуально, коли мова йде про відстеження довжини масиву та областей пам'яті, на які вони посилаються.

Приклад 1: Автоматичне відстеження довжини

const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2

buffer.resize(12);

console.log(float32.byteLength); // 12
console.log(float32.length); // 3

Тут ми створюємо ArrayBuffer з початковим розміром 8 байтів і максимальним розміром 16 байтів. Потім ми створюємо Float32Array, який використовує цей буфер. Коли ми змінюємо розмір буфера до 12 байтів, довжина Float32Array автоматично збільшується до 3, оскільки кожний елемент Float32 займає 4 байти.

Основна ідея полягає в тому, що якщо ви не вказуєте розмір під час створення TypedArray, він буде автоматично відстежувати розмір своєї зв'язаної області пам'яті.

Приклад 2: Фіксований розмір масиву

const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer, 0, 2);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2

buffer.resize(12);

console.log(float32.byteLength); // 8
console.log(float32.length); // 2

У цьому випадку ми явно вказали розмір TypedArray як 2 елементи. Тому, незалежно від того, як ми змінюємо розмір буфера, розмір масиву залишається незмінним.

Приклад 3: Зменшення розміру буфера

const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
const float32 = new Float32Array(buffer, 0, 2);

buffer.resize(7);

console.log(float32.byteLength); // 0
console.log(float32.length); // 0

Якщо розмір буфера зменшується таким чином, що він стає менше, ніж область пам'яті, на яку посилається TypedArray, довжина цього масиву автоматично стає 0.

Ці приклади показують, як розмір TypedArray може змінюватися в залежності від дій, виконаних з пов'язаним ArrayBuffer. Розуміння цих механізмів дозволить вам ефективно працювати з пам'яттю в JavaScript і уникати потенційних проблем.

автор: Bond

Порада

Якщо розмір пов'язаного ArrayBuffer змінюється під час виконання програми, це може вплинути на довжину TypedArray та доступність даних. Завжди будьте в курсі таких змін і плануйте свій код відповідно.

автор: Bond
Порада

Оскільки TypedArray надає прямий доступ до пам'яті, вони є ідеальним вибором для обробки великих масивів даних, таких як графічні дані або звукові потоки. Якщо ви працюєте з великими масивами, розгляньте можливість використання TypedArray для підвищення продуктивності.

автор: Bond
Нотатка

У JavaScript є різні типи TypedArray, такі як Int8Array, Uint8Array, Float32Array тощо. Кожен з них представляє різний тип даних і використовує різний обсяг пам'яті. Перед створенням TypedArray розберіться, який саме тип даних вам потрібен, щоб оптимізувати використання пам'яті.

автор: Bond

Синтаксис

let obj = new TypedArray();
let obj = new TypedArray(length);
let obj = new TypedArray(typedArray);
let obj = new TypedArray(object);

let obj = new TypedArray(buffer);
let obj = new TypedArray(buffer, byteOffset);
let obj = new TypedArray(buffer, byteOffset, length);

Переглядачі

Підтримка: стаціонарні переглядачі
Переглядач Google Chrome Mozilla Firefox Apple Safari Opera Microsoft EDGE Microsoft Internet Explorer
7 4 5.1 11.6 12 10
Підтримка: мобільні переглядачі
Переглядач Mobile Google Android Mobile Google Chrome Mobile Mozilla Firefox Mobile Apple Safari
4 18 4 4.2
Підтримка: серверні переглядачі
Переглядач Node.js Deno
0.10.0 1.0

Приклади

+ запропонувати свій приклад у пісочниці

Одним з простих сценаріїв використання може бути завантаження двійкових даних (наприклад, файлу) з серверу та його аналіз. Це дозволяє зрозуміти, як TypedArray може представляти байти і як з ними працювати.

// Завантажуємо справжній файл (svg-логотип) як двійкові дані
fetch('/img/logo.svg')
    .then(response => response.arrayBuffer())
    .then(buffer => {
        const data = new Uint8Array(buffer);

        console.log('Розмір файлу:', data.length, 'байтів');
        console.log('Перший байт:', data[0]); // 60 — код символу «<»

        // формат текстовий, тож байти можна перетворити на рядок
        const text = new TextDecoder().decode(data);
        console.log(text.slice(0, 40) + '…');
    })
    .catch(error => console.log('Не вдалося завантажити:', error.message));
автор: Bond

TypedArray є ключовим компонентом WebGL, технології для рендерингу 3D графіки в браузерах. Тут TypedArray використовується для передачі вертексних даних, нормалей, UV координат та інших графічних даних до відеокарти.

HTML

<canvas id="glCanvas" width="200" height="120"></canvas>

JS

const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');

if (!gl) {
    console.log('WebGL недоступний у цьому середовищі');
} else {
    const vertices = new Float32Array([
        -1.0, -1.0,
         1.0, -1.0,
        -1.0,  1.0,
         1.0,  1.0,
    ]);

    // Передача даних вершин до буфера WebGL
    const vertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    console.log('Буфер вершин заповнено:', vertices.length, 'координат');
}
автор: Bond

TypedArray може бути вельми корисним при роботі з графічними даними, наприклад, при обробці зображень. Використовуючи TypedArray, можна прямо працювати з байтами зображення, модифікувати їх або аналізувати в реальному часі.

const imageBytes = new Uint8Array(1000*1000*4); // припустимо, це байти зображення RGBА для 1000x1000 зображення

// Інвертуємо кольори для кожного пікселя
for (let i = 0; i < imageBytes.length; i++) {
    imageBytes[i] = 255 - imageBytes[i];
}
автор: Bond

TypedArray також може бути корисним при обробці аудіо даних. Зокрема, вони можуть використовуватися для прямого доступу та маніпуляції з аудіосигналами, такими як модифікація амплітуди чи застосування фільтрів.

const audioSampleRate = 44100;
const audioDuration = 5;
const audioData = new Float32Array(audioSampleRate * audioDuration); // 5 секунд стерео звуку

// Створюємо простий синусоїдний тон
for (let i = 0; i < audioData.length; i++) {
    audioData[i] = Math.sin(2 * Math.PI * 440 * i / audioSampleRate);
}
автор: Bond

Коментарі

Коментарів ще немає — будьте першим!

Відповідь для

Як форматувати текст?
Пишемо Виходить
**важливо**
*акцент*
~~застаріле~~
Виділення в тексті. Те саме роблять кнопки панелі, що спливає над виділеним.
## Як працює каскад
### Порядок оголошень
Заголовки всередині тексту. Найбільший не потрібен — він у сторінки вже є.
[[css/property/color]] Посилання на сторінку довідника. Наберіть [[ — поле саме підкаже шляхи, а хибний підкреслить хвилею.
[MDN](https://developer.mozilla.org) Посилання на чужий сайт.
![Схема каскаду](https://site.com/схема.png) Картинка. Опис обов'язковий: його читають пошуковик і незрячі.
Задайте `display: grid` контейнеру Код усередині речення.
```css
.card { display: grid }
```
Код блоком. Мова після трьох лапок вмикає підсвітку.
- Походження
1. Походження
Перелік: маркований і нумерований.
- [ ] дописати приклади
- [x] перевірити в Firefox
Перелік завдань із галочками. Пробіл у порожніх дужках обов'язковий.
> Порядок важить лише за рівної ваги. Цитата на всю ширину абзацу.
Специфічність
: вага селектора; більша перемагає
Список означень: термін, а під ним пояснення з відступом. Пробіл після двокрапки обов'язковий.
Каскад має три критерії[^1]
[^1]: Походження, специфічність, порядок.
Виноска: номер у тексті, примітка внизу сторінки. Без згадки [^1] у тексті примітка не з'явиться.
Відповідь: ||сорок два|| Ховає те, що між рисками: читач бачить на цьому місці розмиту пляму, а решта речення лишається звичайною. Клац — і текст відкрито.
|| Показати рішення
Задайте контейнеру `display: grid`.
||
Ховає цілі абзаци. На сторінці видно лише підпис із першого рядка («Показати рішення»), решта розгортається клацанням по ньому. Закривні риски — окремим рядком.
Порожній рядок Новий абзац. Щоб перенести рядок усередині абзацу, поставте \ в його кінці.

Увійдіть — коментар з'явиться одразу, без капчі й очікування перевірки.

Пропозиція правки

Ваша версія — : після перевірки замінить чинну. Нова порада чи нотатка — з'явиться на сторінці після перевірки.

Як форматувати текст?
Пишемо Виходить
**важливо**
*акцент*
~~застаріле~~
Виділення в тексті. Те саме роблять кнопки панелі, що спливає над виділеним.
## Як працює каскад
### Порядок оголошень
Заголовки всередині тексту. Найбільший не потрібен — він у сторінки вже є.
[[css/property/color]] Посилання на сторінку довідника. Наберіть [[ — поле саме підкаже шляхи, а хибний підкреслить хвилею.
[MDN](https://developer.mozilla.org) Посилання на чужий сайт.
![Схема каскаду](https://site.com/схема.png) Картинка. Опис обов'язковий: його читають пошуковик і незрячі.
Задайте `display: grid` контейнеру Код усередині речення.
```css
.card { display: grid }
```
Код блоком. Мова після трьох лапок вмикає підсвітку.
- Походження
1. Походження
Перелік: маркований і нумерований.
- [ ] дописати приклади
- [x] перевірити в Firefox
Перелік завдань із галочками. Пробіл у порожніх дужках обов'язковий.
> Порядок важить лише за рівної ваги. Цитата на всю ширину абзацу.
Специфічність
: вага селектора; більша перемагає
Список означень: термін, а під ним пояснення з відступом. Пробіл після двокрапки обов'язковий.
Каскад має три критерії[^1]
[^1]: Походження, специфічність, порядок.
Виноска: номер у тексті, примітка внизу сторінки. Без згадки [^1] у тексті примітка не з'явиться.
Відповідь: ||сорок два|| Ховає те, що між рисками: читач бачить на цьому місці розмиту пляму, а решта речення лишається звичайною. Клац — і текст відкрито.
|| Показати рішення
Задайте контейнеру `display: grid`.
||
Ховає цілі абзаци. На сторінці видно лише підпис із першого рядка («Показати рішення»), решта розгортається клацанням по ньому. Закривні риски — окремим рядком.
Порожній рядок Новий абзац. Щоб перенести рядок усередині абзацу, поставте \ в його кінці.

Ви гість — діють добові ліміти. Увійдіть, щоб пропонувати без капчі.

Ваша версія секції «»: після перевірки замінить чинну.

Як форматувати текст?
Пишемо Виходить
**важливо**
*акцент*
~~застаріле~~
Виділення в тексті. Те саме роблять кнопки панелі, що спливає над виділеним.
## Як працює каскад
### Порядок оголошень
Заголовки всередині тексту. Найбільший не потрібен — він у сторінки вже є.
[[css/property/color]] Посилання на сторінку довідника. Наберіть [[ — поле саме підкаже шляхи, а хибний підкреслить хвилею.
[MDN](https://developer.mozilla.org) Посилання на чужий сайт.
![Схема каскаду](https://site.com/схема.png) Картинка. Опис обов'язковий: його читають пошуковик і незрячі.
Задайте `display: grid` контейнеру Код усередині речення.
```css
.card { display: grid }
```
Код блоком. Мова після трьох лапок вмикає підсвітку.
- Походження
1. Походження
Перелік: маркований і нумерований.
- [ ] дописати приклади
- [x] перевірити в Firefox
Перелік завдань із галочками. Пробіл у порожніх дужках обов'язковий.
> Порядок важить лише за рівної ваги. Цитата на всю ширину абзацу.
Специфічність
: вага селектора; більша перемагає
Список означень: термін, а під ним пояснення з відступом. Пробіл після двокрапки обов'язковий.
Каскад має три критерії[^1]
[^1]: Походження, специфічність, порядок.
Виноска: номер у тексті, примітка внизу сторінки. Без згадки [^1] у тексті примітка не з'явиться.
Відповідь: ||сорок два|| Ховає те, що між рисками: читач бачить на цьому місці розмиту пляму, а решта речення лишається звичайною. Клац — і текст відкрито.
|| Показати рішення
Задайте контейнеру `display: grid`.
||
Ховає цілі абзаци. На сторінці видно лише підпис із першого рядка («Показати рішення»), решта розгортається клацанням по ньому. Закривні риски — окремим рядком.
Порожній рядок Новий абзац. Щоб перенести рядок усередині абзацу, поставте \ в його кінці.

Ви гість — діють добові ліміти. Увійдіть, щоб пропонувати без капчі.

Ваша версія опису «»: після перевірки замінить чинну.

Як форматувати текст?
Пишемо Виходить
**важливо**
*акцент*
~~застаріле~~
Виділення в тексті. Те саме роблять кнопки панелі, що спливає над виділеним.
## Як працює каскад
### Порядок оголошень
Заголовки всередині тексту. Найбільший не потрібен — він у сторінки вже є.
[[css/property/color]] Посилання на сторінку довідника. Наберіть [[ — поле саме підкаже шляхи, а хибний підкреслить хвилею.
[MDN](https://developer.mozilla.org) Посилання на чужий сайт.
![Схема каскаду](https://site.com/схема.png) Картинка. Опис обов'язковий: його читають пошуковик і незрячі.
Задайте `display: grid` контейнеру Код усередині речення.
```css
.card { display: grid }
```
Код блоком. Мова після трьох лапок вмикає підсвітку.
- Походження
1. Походження
Перелік: маркований і нумерований.
- [ ] дописати приклади
- [x] перевірити в Firefox
Перелік завдань із галочками. Пробіл у порожніх дужках обов'язковий.
> Порядок важить лише за рівної ваги. Цитата на всю ширину абзацу.
Специфічність
: вага селектора; більша перемагає
Список означень: термін, а під ним пояснення з відступом. Пробіл після двокрапки обов'язковий.
Каскад має три критерії[^1]
[^1]: Походження, специфічність, порядок.
Виноска: номер у тексті, примітка внизу сторінки. Без згадки [^1] у тексті примітка не з'явиться.
Відповідь: ||сорок два|| Ховає те, що між рисками: читач бачить на цьому місці розмиту пляму, а решта речення лишається звичайною. Клац — і текст відкрито.
|| Показати рішення
Задайте контейнеру `display: grid`.
||
Ховає цілі абзаци. На сторінці видно лише підпис із першого рядка («Показати рішення»), решта розгортається клацанням по ньому. Закривні риски — окремим рядком.
Порожній рядок Новий абзац. Щоб перенести рядок усередині абзацу, поставте \ в його кінці.

Ви гість — діють добові ліміти. Увійдіть, щоб пропонувати без капчі.

Зворотний зв'язок
Вхід