Ikkilik ma'lumot va fayllar

ArrayBuffer, TypedArray

Web-ishlab chiqishda biz ko'pincha ikkilik (binary) ma'lumot bilan ishlashga to'g'ri kelamiz โ€” rasm fayllari, tarmoqdan kelgan baytlar, arxivlar va hokazo. JavaScriptda bularning barchasi zamirida ArrayBuffer turadi: bu โ€” belgilangan uzunlikdagi xom baytlar saqlanadigan xotira bloki. Buferning o'zi bilan bevosita ishlab bo'lmaydi โ€” uning ustiga ko'rinish (view), ya'ni TypedArray yoki DataView qo'yiladi.

ArrayBuffer โ€” xom xotira bloki

ArrayBuffer โ€” konstruktor bo'lib, u belgilangan baytlar sonidan iborat, nol bilan to'ldirilgan uzluksiz xotira maydonini yaratadi:

buffer-yaratish.js
// natija shu yerda chiqadi

Bu yerda 16 baytlik maydon ajratildi va u nollar bilan to'ldirildi. byteLength xususiyati buferning uzunligini (baytlarda) qaytaradi.

ArrayBuffer โ€” bu oddiy massiv emas! Uni Array bilan aralashtirmang. Muhim farqlar: uning uzunligi qat'iy belgilangan (o'zgartirib bo'lmaydi), u aynan shuncha baytni band qiladi, va uning elementiga buffer[0] deb murojaat qilib bo'lmaydi. ArrayBuffer โ€” bu shunchaki xotira bo'lagi, unda nima saqlanayotgani noma'lum, u faqat baytlar ketma-ketligi.

Buferdagi baytlarga kirish uchun bizga ko'rinish obyekti kerak. Ko'rinish o'zida hech qanday ma'lumot saqlamaydi โ€” u faqat buferdagi baytlarni qanday talqin qilishni belgilaydigan "oyna"dir.

TypedArray ko'rinishlari

Ko'rinishlarning umumiy nomi โ€” TypedArray (turlangan massiv). Bu bitta konstruktor emas, balki bir necha konstruktorlarning umumiy nomi. Ular buferdagi baytlarni turli formatlarda talqin qiladi:

Nomdagi son bitlar sonini bildiradi. Masalan, Uint16Array โ€” har bir raqamga 16 bit (2 bayt) ajratadi. Shu sabab 16 baytlik bufer Uint16Array orqali 8 ta element, Uint32Array orqali 4 ta element bo'lib ko'rinadi:

korinishlar.js
// natija shu yerda chiqadi
length โ€” ko'rinishdagi elementlar soni, byteLength esa baytlar soni. Ular har xil ko'rinishlar uchun turlicha bo'ladi, chunki har bir element turli miqdorda bayt egallaydi.

Indeks bilan ishlash

TypedArray oddiy massivga juda o'xshaydi: unga indeks orqali murojaat qilish, qiymat yozish va o'qish mumkin:

indeks-yozish.js
// natija shu yerda chiqadi
Uint8Array faqat 0..255 saqlaydi. Agar chegaradan chiqqan qiymat yozsangiz, u xatolik bermaydi, balki ortiqcha bitlar tashlanadi. Yuqorida 300 sonining faqat quyi 8 biti saqlanib, natija 44 bo'ldi (300 - 256 = 44). Bu "o'ralib qolish" (overflow) deyiladi.

Agar Uint8ClampedArray ishlatilsa, chegaradan chiqqan qiymat kesiladi (0 dan pastini 0 ga, 255 dan yuqorisini 255 ga):

clamped.js
// natija shu yerda chiqadi

Bufer va ko'rinish bir xotirani baham ko'radi

Bu โ€” eng muhim tushunchalardan biri. Bir xil buferga bir nechta ko'rinish qo'yish mumkin. Ular bitta xotirani ko'rsatadi, shuning uchun biri orqali yozilgan bayt boshqasi orqali darhol ko'rinadi:

bir-xotira.js
// natija shu yerda chiqadi

Har bir TypedArrayning buffer xususiyati orqali uning asosidagi ArrayBufferga yetib borish mumkin. Shu bilan bir buferga yangi ko'rinish qo'shsa bo'ladi:

buffer-xususiyat.js
// natija shu yerda chiqadi
TypedArrayni yaratishning ikki yo'li bor: (1) mavjud buferni berish โ€” new Uint8Array(buffer); (2) uzunlik berish โ€” new Uint8Array(8), bunda ichida yangi bufer avtomatik yaratiladi. Ikkinchi holatda ham arr.buffer mavjud bo'ladi.

TypedArray metodlari

TypedArray oddiy Arrayning deyarli barcha metodlarini qo'llab-quvvatlaydi: map, forEach, filter, reduce, find, slice, indexOf va hokazo:

typedarray-metodlar.js
// natija shu yerda chiqadi

Lekin ba'zi metodlar yo'q: push, pop, shift, unshift, splice โ€” chunki bular massiv uzunligini o'zgartiradi, TypedArray uzunligi esa qat'iy (buferga bog'liq).

Muhim maxsus metod โ€” set. U bitta TypedArrayning barcha qiymatlarini boshqasiga (yoki oddiy massivni) berilgan pozitsiyadan boshlab ko'chiradi:

typedarray-set.js
// natija shu yerda chiqadi

Yana bir metod โ€” subarray. U ma'lumotni nusxalamasdan, xuddi shu buferning bir qismiga yangi ko'rinish qaytaradi (ular xotirani baham ko'radi):

subarray.js
// natija shu yerda chiqadi
slice va subarray farqi: slice ma'lumotni nusxalaydi (yangi bufer), subarray esa faqat yangi oyna beradi (bir xil bufer). Xotira tejash kerak bo'lsa subarray tezroq va arzonroq.

DataView โ€” moslashuvchan ko'rinish

DataView โ€” buferga eng past darajadagi, eng moslashuvchan kirish usuli. TypedArraydan farqi: DataViewda format oldindan qat'iy belgilanmaydi. Aksincha, har bir o'qish/yozishda formatni siz o'zingiz aytasiz โ€” getUint8, getInt32, getFloat64 va hokazo:

dataview.js
// natija shu yerda chiqadi

DataViewning asosiy afzalligi โ€” bitta buferda turli formatdagi ma'lumotlarni aralash saqlash mumkin. Masalan, tarmoq protokoli yoki fayl formati sarlavhasi: dastlabki 2 bayt โ€” versiya (Uint16), keyingi 4 bayt โ€” o'lcham (Uint32) va hokazo. Bunday holatda DataView ideal.

DataView metodlarida yana bir muhim parametr bor โ€” little-endian / big-endian (baytlar tartibi). Ko'p baytli sonlar xotirada ikki xil tartibda saqlanishi mumkin. Uchinchi argument true berilsa little-endian ishlatiladi:

dataview-endian.js
// natija shu yerda chiqadi
Ko'p platformalarda xotira little-endian (kichik bayt oldinda) tartibida saqlanadi. Tarmoq protokollarida esa ko'pincha big-endian ishlatiladi. Fayl yoki tarmoq formati bilan ishlaganda tartibni albatta tekshiring โ€” noto'g'ri tartib qiymatlarni buzadi.

Xulosa