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, що надає широкі можливості для оптимізації та контролю над вашими даними.
Робота з пам'яттю через 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.
Зміна розміру та відстеження довжини
Коли ви працюєте з 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 і уникати потенційних проблем.
Порада: | Якщо розмір пов'язаного |
Порада: | Оскільки |
Нотатка: | У JavaScript є різні типи |
Синтаксис
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);
Переглядачі
Переглядач | |||||
---|---|---|---|---|---|
7 |
4 |
5.1 |
11.6 |
12 |
Переглядач | ||||
---|---|---|---|---|
4 |
4.2 |
4 |
18 |
Переглядач | ||
---|---|---|
0.10.0 |
1.0 |
Приклади
Одним з простих сценаріїв використання може бути завантаження двійкових даних (наприклад, файлу) з серверу та його аналіз. Це дозволяє зрозуміти, як TypedArray
може представляти байти і як з ними працювати.
// Спочатку ми використовуємо fetch API для завантаження двійкового файлу
fetch('path_to_binary_file.bin')
.then(response => response.arrayBuffer())
.then(buffer => {
// Після завантаження ми конвертуємо Array Buffer до TypedArray
const data = new Uint8Array(buffer);
// Тепер ми можемо працювати з окремими байтами файлу. Наприклад, вивести перший байт:
console.log(data[0]);
// Або, якщо це текстовий файл, ми можемо конвертувати його в строку:
const textDecoder = new TextDecoder();
const text = textDecoder.decode(data);
console.log(text);
});
TypedArray
може бути вельми корисним при роботі з графічними даними, наприклад, при обробці зображень. Використовуючи TypedArray
, можна прямо працювати з байтами зображення, модифікувати їх або аналізувати в реальному часі.
const imageBytes = new Uint8Array(1000*1000*4); // припустимо, це байти зображення RGBА для 1000x1000 зображення
// Інвертуємо кольори для кожного пікселя
for (let i = 0; i < imageBytes.length; i++) {
imageBytes[i] = 255 - imageBytes[i];
}
TypedArray
є ключовим компонентом WebGL, технології для рендерингу 3D графіки в браузерах. Тут TypedArray
використовується для передачі вертексних даних, нормалей, UV координат та інших графічних даних до відеокарти.
const vertices = new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0
]);
// Передача даних вертексів до буфера WebGL
const gl = someWebGLContext;
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
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);
}