Mundarija (38)
- Bu darsda
- 1. Nega bu kerak?
- 2. Bayt va Uint8Array
- 2.1 Bayt nima?
- 2.2 Birinchi Uint8Array
- 2.3 Massivga o'xshaydi, lekin massiv emas
- 3. Chegaralar: toshish va yaxlitlash
- 3.1 0–255 dan tashqari son
- 3.2 map ham toshadi
- 3.3 Turlar oilasi
- 4. Kasr turlari va Float16Array
- 4.1 Aniqlik — xotira evaziga
- 4.2 Float16Array — yarim aniqlik
- 5. ArrayBuffer: xotira va unga "ko'zoynaklar"
- 5.1 Xotiraning o'zi
- 5.2 Bir xotira, ikki ko'rinish
- 5.3 subarray va slice
- 6. DataView va bayt tartibi
- 6.1 Endianness
- 6.2 DataView
- 7. Matn ↔ baytlar
- 7.1 TextEncoder va TextDecoder
- 7.2 Hex va Base64
- 8. O'lchami o'zgaradigan va ko'chiriladigan xotira
- 9. Ko'p uchraydigan xatolar
- 9.1 push is not a function
- 9.2 Jim toshish
- 9.3 Bayt tartibi adashgan
- 9.4 subarray ni nusxa deb o'ylash
- 9.5 Typed array'ni muzlatish
- 10. Mashqlar
- 1-mashq (oson): RGB rang
- 2-mashq (o'rta): Tarozi xabari
- 3-mashq (qiyin): O'z hexdan funksiyangiz
- 4-mashq: Mashqlar qadami — fayl imzosini aniqlash
- 11. Real ishda
- Xulosa
- Manbalar
JavaScript typed arrays: ArrayBuffer, Uint8Array va binar ma'lumot bilan ishlash
Qisqacha: Typed array — bir xil turdagi sonlarni qat'iy o'lchamdagi xotirada saqlaydigan maxsus massiv:
new Uint8Array(4)— to'rtta baytli katak, har birida 0–255. Xotiraning o'zi —ArrayBuffer, typed array vaDataViewesa unga turli "ko'zoynak" bilan qaraydi. Fayl, rasm, tarmoq paketi, shifrlash — hammasi baytlar, va JavaScript ular bilan aynan shu vositalar orqali ishlaydi.
Bu darsda
- Bayt nima ekanini va nega oddiy massiv baytlar uchun noqulayligini tushuntira olasiz.
Uint8Array,Int32Array,Float64Array,Float16Arrayni yarata olasiz va ularning chegaralarini (toshish, yaxlitlash) bilasiz.ArrayBufferva bir xotiraga qaraydigan bir nechta ko'rinishni (view) tushuntira olasiz.DataViewbilan sonni kerakli bayt tartibida (endianness) yoza va o'qiy olasiz.- Matnni baytlarga (
TextEncoder) va baytlarni hex/Base64 ko'rinishiga aylantira olasiz.
Oldin bilishingiz kerak: Massivga o'xshash obyektlar va teshikli massivlar, Bitwise operatorlar, Son yozish shakllari va sanoq tizimlari, Unicode va emoji.
1. Nega bu kerak?
Kompyuterdagi har qanday fayl — rasm, PDF, musiqa — oxir-oqibat sonlar ketma-ketligi. Har bir son 0 dan 255 gacha. Masalan, har bir PNG rasm aynan shu sakkiz son bilan boshlanadi:
137 80 78 71 13 10 26 10Bu — PNG faylining "imzosi". Dastur faylni ochganda avval shu sonlarga qaraydi va "bu PNG" deb biladi. Fayl nomidagi .png ga emas — ichidagi baytlarga.
Bunday sonlarni oddiy massivda saqlash mumkinmi? Ha, lekin noqulay. Oddiy massivning har katagiga istalgan narsa sig'adi: 255, -7.5, "salom", obyekt. JavaScript har katak uchun "bu yerda nima turibdi?" degan ma'lumotni ham saqlaydi. Bayt uchun esa bu ortiqcha: unda faqat 0–255 oralig'idagi butun son bo'ladi.
Hayotdan o'xshatish: bozordagi tuxum kassetasi. Unda 30 ta katak, har birining o'lchami bir xil, har biriga aynan bitta tuxum sig'adi. Tarvuz qo'yib bo'lmaydi, 31-tuxum uchun joy yo'q. Lekin aynan shu qat'iylik uni ixcham va tez qiladi: necha tuxum borligini sanash shart emas, istalgan katakni darhol topasiz. Oddiy massiv esa qop — hamma narsa sig'adi, lekin har safar ichini titkilash kerak.
Typed array — aynan shunday kasseta. Har katak bir xil turda va bir xil o'lchamda, uzunligi esa yaratilganda qotadi.
Bu dars vazifalar ga tegmaydi: u yerda baytlar bilan ish yo'q. Lekin keyingi qismlarda — fayl yuklash (File va Blob), tarmoq, shifrlash — typed array'larsiz ish bitmaydi. Bugun poydevorni qo'yamiz.
2. Bayt va Uint8Array
2.1 Bayt nima?
Bayt (byte) — kompyuter xotirasining eng kichik "katagi". Bitta bayt — sakkiz bit, ya'ni sakkizta 0 yoki 1. Bitwise operatorlar darsida bitlar bilan ishlagan edik. Sakkiz bit bilan 2⁸ = 256 xil son yozish mumkin: 0 dan 255 gacha.
Baytlar ko'pincha o'n oltilik (hex) ko'rinishda yoziladi — har bayt aynan ikki belgi: 0x00 dan 0xff gacha (Sanoq tizimlari). PNG imzosining boshi 137 — hex'da 0x89, keyingi uchtasi 0x50 0x4e 0x47.
2.2 Birinchi Uint8Array
Uint8Array — har katagi bitta bayt bo'lgan typed array. Nomi o'qiladi: Unsigned (ishorasiz, ya'ni manfiy yo'q) int (butun) 8 (bit).
const imzo = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
console.log(imzo); // Uint8Array(4) [ 137, 80, 78, 71 ]
console.log(imzo.length); // 4
console.log(imzo[1]); // 80Hex'da yozdik — konsol o'nlik sonda ko'rsatdi. Ikkalasi bitta son: 0x50 va 80 bir xil. Node turini va uzunligini oldiga yozadi: Uint8Array(4).
Uzunlik bilan yaratsangiz, hamma katak 0 bo'ladi — teshik emas (Teshikli massivlar darsidagi new Array(3) dan farqi shu):
const katak = new Uint8Array(3);
console.log(katak); // Uint8Array(3) [ 0, 0, 0 ]2.3 Massivga o'xshaydi, lekin massiv emas
Typed array — oldingi darsdagi massivga o'xshash oilaning a'zosi. Unda length va indekslar bor. Ko'p tanish metodlar ham bor: map, filter, reduce, forEach, includes, slice, join. Lekin Array.isArray false deydi, va uzunlikni o'zgartiradigan metodlar yo'q:
const baytlar = new Uint8Array(3);
baytlar.push(7);TypeError: baytlar.push is not a functionTarjimasi: "baytlar.push — funksiya emas". push, pop, splice yo'q — kassetaga yangi katak qo'shib bo'lmaydi. Chegaradan tashqariga yozish esa jimgina e'tiborsiz qoladi:
const baytlar = new Uint8Array(3);
baytlar[5] = 9;
console.log(baytlar); // Uint8Array(3) [ 0, 0, 0 ]
console.log(baytlar.length); // 3Oddiy massivda [5] = 9 teshik yaratib, massivni cho'zardi. Typed array'da esa — hech narsa. Teshik ham, cho'zilish ham yo'q.
Tekshirib ko'ring:
new Uint8Array(2)dan keyinArray.isArray(x)vax.lengthnima qaytaradi? Oddiy massivga qanday aylantirasiz?
Javob
false va 2. Oddiy massivga — oldingi darsdagi usul: Array.from(x) yoki [...x]. Typed array iterable, shuning uchun spread ham ishlaydi.
3. Chegaralar: toshish va yaxlitlash
3.1 0–255 dan tashqari son
Uint8Array katagiga 256 yoki -1 yozsangiz nima bo'ladi? Xato chiqmaydi — son "aylanib" o'tadi:
const b = new Uint8Array(4);
b[0] = 255;
b[1] = 256;
b[2] = -1;
b[3] = 300;
console.log(b); // Uint8Array(4) [ 255, 0, 255, 44 ]Bu — toshish (overflow). Avtomobil spidometridagi probeg hisoblagichini eslang: 999 999 dan keyin 000 000 ga qaytadi. Bayt ham shunday: 255 dan keyin 0 keladi. 256 — 0, 300 — 300 - 256 = 44, -1 — 255. Qoidani oddiy so'z bilan aytsak: sig'maydigan songa 256 ni qo'shib yoki ayirib, uni 0–255 oralig'iga "qaytaradi" (-1 + 256 = 255). Bitlar tilida esa — sonning faqat oxirgi sakkiz biti olinadi, qolgani tashlanadi.
Rasm bilan ishlaganda bu yomon: piksel yorqinligi 250 ga 10 qo'shsangiz, eng yorug' nuqta to'satdan qora (4) bo'ladi. Shuning uchun maxsus "qisuvchi" tur bor — Uint8ClampedArray. U toshib o'tmaydi, chegarada to'xtaydi va kasrni yaxlitlaydi:
const piksel = new Uint8ClampedArray([300, -5, 12.7]);
console.log(piksel); // Uint8ClampedArray(3) [ 255, 0, 13 ]300 — 255 da to'xtadi, -5 — 0 da. Brauzerdagi <canvas> rasm piksellarini aynan shu turda beradi.
3.2 map ham toshadi
Typed array'ning map metodi xuddi shu turdagi yangi typed array qaytaradi. Natija sig'masa — u ham toshadi:
const yorugligi = new Uint8Array([200, 240, 250]);
const yangi = yorugligi.map((x) => x + 10);
console.log(yangi); // Uint8Array(3) [ 210, 250, 4 ]250 + 10 = 260 → 4. Oddiy son kerak bo'lsa, avval oddiy massivga o'ting: Array.from(yorugligi, (x) => x + 10) — [ 210, 250, 260 ].
3.3 Turlar oilasi
Uint8Array — oilaning bir a'zosi. Qolganlari katak o'lchami va son turida farq qiladi:
| Tur | Katak | Qiymatlar |
|---|---|---|
Int8Array |
1 bayt | -128 … 127 |
Uint8Array, Uint8ClampedArray |
1 bayt | 0 … 255 |
Int16Array / Uint16Array |
2 bayt | -32 768 … 32 767 / 0 … 65 535 |
Int32Array / Uint32Array |
4 bayt | ±2,1 mlrd / 0 … 4,29 mlrd |
Float16Array |
2 bayt | kasr, ~3 xona aniqlik |
Float32Array |
4 bayt | kasr, ~7 xona aniqlik |
Float64Array |
8 bayt | oddiy JS soni (number) |
BigInt64Array / BigUint64Array |
8 bayt | BigInt |
"Int" — ishorali (manfiy bo'lishi mumkin), "Uint" — ishorasiz. Raqam — bitlar soni. Har turdagi bitta katak necha bayt ekanini BYTES_PER_ELEMENT aytadi:
console.log(Uint8Array.BYTES_PER_ELEMENT); // 1
console.log(Float64Array.BYTES_PER_ELEMENT); // 8
console.log(new Int32Array(3).byteLength); // 12byteLength — butun typed array xotirada necha bayt egallashi: 3 katak × 4 bayt = 12.
Butun turlarga kasr yozilsa, kasr qismi tashlab yuboriladi (yaxlitlanmaydi):
console.log(new Int32Array([1.9, -1.9])); // Int32Array(2) [ 1, -1 ]
console.log(new Int8Array([127, 128])); // Int8Array(2) [ 127, -128 ]1.9 → 1, -1.9 → -1. Int8Array da esa 128 sig'madi va manfiy tomonga aylanib o'tdi: -128.
Tekshirib ko'ring:
new Uint8Array([257, 3.99])qanday chiqadi?Uint8ClampedArrayda-chi?
Javob
Uint8Array(2) [ 1, 3 ] — 257 aylanib 1 bo'ldi, 3.99 ning kasr qismi tashlandi. Uint8ClampedArray(2) [ 255, 4 ] — 257 chegarada to'xtadi, 3.99 esa yaxlitlandi. Ikki tur ikki xil qoida bilan ishlaydi.
4. Kasr turlari va Float16Array
4.1 Aniqlik — xotira evaziga
JavaScript'ning oddiy soni — 8 baytlik kasr son (Number turi). Float64Array aynan shunday katak. Float32Array — ikki baravar kichik, lekin aniqligi kamroq:
console.log(new Float64Array([0.1])[0]); // 0.1
console.log(new Float32Array([0.1])[0]); // 0.100000001490116120.1 ni 4 baytga sig'dirib bo'lmadi — eng yaqin son saqlandi. O'qiganda u 8 baytlik JS soniga qaytadi va "dum" ko'rinib qoladi.
Nega aniqligi past turni tanlashadi? Xotira uchun. 3D o'yindagi millionlab nuqta yoki sun'iy intellekt modelidagi milliardlab son — har birida 4 bayt tejash gigabaytlarni tejaydi. Ekrandagi nuqtaning o'rni uchun 7 xona aniqlik yetarli.
4.2 Float16Array — yarim aniqlik
2025-yilda JavaScript'ga yana kichikroq tur qo'shildi — Float16Array, har katagi 2 bayt. U grafika kartalari va sun'iy intellekt modellarida keng ishlatiladigan formatga mos keladi.
const yarim = new Float16Array([0.1, 65504, 70000]);
console.log(yarim[0]); // 0.0999755859375
console.log(yarim[1]); // 65504
console.log(yarim[2]); // Infinity
console.log(Math.f16round(0.1)); // 0.0999755859375Aniqlik — taxminan uch xona. Eng katta son — 65 504; undan kattasi Infinity bo'ladi. Math obyekti darsida va'da qilgan Math.f16round — oddiy sonni xuddi shu formatga yaxlitlab ko'rsatadi: Float16Array ga yozsangiz, aynan shu son saqlanadi.
Float16Array 2025-yil aprelidan beri barcha asosiy brauzerlarda bor (Chrome 135, Firefox 129, Safari 18.2 — "Baseline 2025"). Node 24 da ham ishlaydi.
5. ArrayBuffer: xotira va unga "ko'zoynaklar"
5.1 Xotiraning o'zi
Typed array ichida yana bir obyekt yashiringan — ArrayBuffer. Bu — xom xotira bo'lagi: bir necha bayt, xolos. Unda "son", "tur" degan tushuncha yo'q. Uni to'g'ridan-to'g'ri o'qib ham, yozib ham bo'lmaydi:
const xotira = new ArrayBuffer(4);
console.log(xotira.byteLength); // 4
console.log(xotira[0]); // undefinedxotira[0] — undefined. ArrayBuffer — shunchaki "4 bayt joy". U bilan ishlash uchun unga ko'rinish (view) kerak: typed array yoki DataView.
Hayotdan o'xshatish: qog'ozga yozilgan 2026 raqamlari. Ularni to'rtta alohida raqam deb o'qish mumkin — 2, 0, 2, 6. Yoki bitta son deb — ikki ming yigirma olti. Qog'oz bitta, yozuv o'zgarmadi — faqat qanday o'qishni tanladingiz. ArrayBuffer — qog'oz, typed array — o'qish usuli ("ko'zoynak").
5.2 Bir xotira, ikki ko'rinish
Bitta ArrayBuffer ga ikki xil typed array bilan qaraymiz:
const xotira = new ArrayBuffer(4);
const baytlar = new Uint8Array(xotira);
const butun = new Uint32Array(xotira);
baytlar[0] = 232;
baytlar[1] = 3;
console.log(butun[0]); // 1000
console.log(butun.length); // 1baytlar orqali ikkita baytni yozdik, butun orqali esa bitta son o'qidik — 1000. Ikkalasi bitta xotiraga qaraydi: biri uni 4 ta bir baytli katak deb ko'radi, ikkinchisi — bitta to'rt baytli son.
Sxemada kuzating: to'rt bayt — bitta ArrayBuffer, Uint8Array va Uint32Array — unga qaraydigan ikki ko'rinish:
flowchart TB
U8["Uint8Array: 4 ta katak — 232, 3, 0, 0"]
subgraph X["ArrayBuffer — 4 bayt"]
direction LR
B0["0: e8"] --- B1["1: 03"] --- B2["2: 00"] --- B3["3: 00"]
end
U32["Uint32Array: 1 ta katak — 1000"]
U8 -- "har baytni alohida" --> X
U32 -- "4 baytni bitta son" --> XNega aynan 1000? Ko'p baytli sonda har keyingi bayt 256 barobar "og'irroq" — xuddi o'nlik sonda har keyingi xona 10 barobar og'irroq bo'lgani kabi. Bizda katta bayt — 3, kichigi — 232:
console.log(3 * 256 + 232); // 1000
console.log((1000).toString(16)); // 3e8Hex'da 1000 — 0x03e8: katta bayt 03, kichik bayt e8 (232). Lekin xotirada ular teskari tartibda turibdi: avval kichik qismi e8, keyin 03. Bu tartibning nomi bor — keyingi bo'limda.
5.3 subarray va slice
Typed array'ning bir qismi kerak bo'lsa, ikki metod bor — va ular jiddiy farq qiladi:
const imzo = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
const oyna = imzo.subarray(1, 3);
const nusxa = imzo.slice(1, 3);
oyna[0] = 0;
console.log(imzo[1]); // 0
console.log(nusxa[0]); // 80subarray — yangi ko'rinish, xotira o'sha. Unga yozsangiz, asl typed array ham o'zgaradi. slice esa xotirani nusxalaydi — oddiy massivdagi slice kabi. Katta fayllarda subarray tez (hech narsa nusxalanmaydi), lekin Havola semantikasi darsidagi tuzoq qaytadi: "nusxa" deb o'ylagan narsangiz aslida o'sha xotira.
Tekshirib ko'ring:
const a = new Uint8Array(4); const b = new Uint8Array(a.buffer); b[0] = 5;—a[0]nima?bufferxususiyati nima beradi deb o'ylaysiz?
Javob
5. a.buffer — a ning ostidagi ArrayBuffer. b o'sha xotiraga yangi ko'rinish yaratdi, shuning uchun b ga yozilgani a da ko'rinadi.
6. DataView va bayt tartibi
6.1 Endianness
Bir necha baytli sonni xotiraga ikki xil tartibda yozish mumkin. 1000 = 0x03e8 ni olaylik:
- Big-endian — "katta uchi oldinda":
03 e8. Biz sonlarni qog'ozga shunday yozamiz: katta xona chapda. - Little-endian — "kichik uchi oldinda":
e8 03. Deyarli barcha zamonaviy kompyuter va telefon protsessorlari xotirada shunday saqlaydi.
Endianness (bayt tartibi) — ko'p baytli son xotirada qaysi tartibda turishi. Sana yozishga o'xshaydi: "2026-10-04" va "04.10.2026" — sana bir xil, tartib boshqa. Kim yozgani va kim o'qishini bilmasangiz, 04-oktabrni 10-aprel deb o'qib qo'yishingiz mumkin.
Typed array'lar har doim kompyuterning o'z tartibida ishlaydi — shuning uchun yuqorida e8 03 chiqdi. Lekin fayl formatlari va tarmoq protokollari tartibni o'zi belgilaydi. PNG ichidagi sonlar, masalan, big-endian. Boshqa kompyuterdan kelgan baytlarni to'g'ri o'qish uchun tartibni aniq ko'rsatish kerak.
6.2 DataView
DataView — tur va tartibni har o'qishda o'zingiz tanlaydigan ko'rinish:
const xotira = new ArrayBuffer(4);
const dv = new DataView(xotira);
const baytlar = new Uint8Array(xotira);
dv.setUint32(0, 1000);
console.log(baytlar); // Uint8Array(4) [ 0, 0, 3, 232 ]
dv.setUint32(0, 1000, true);
console.log(baytlar); // Uint8Array(4) [ 232, 3, 0, 0 ]baytlar — o'sha xotiraga ikkinchi ko'rinish: u har yozuvdan keyin baytlarni ko'rsatadi. setUint32(joy, son) — joy baytidan boshlab 4 baytli son yozadi. Uchinchi argument berilmasa — big-endian (0, 0, 3, 232). true — little-endian (232, 3, 0, 0). O'qish ham xuddi shunday: getUint32(joy, kichikOldinmi).
Tartib adashsa nima bo'lishini ko'ring:
const dv = new DataView(new ArrayBuffer(4));
dv.setUint32(0, 1000);
console.log(dv.getUint32(0)); // 1000
console.log(dv.getUint32(0, true)); // 3892510720Big-endian yozib, little-endian o'qisak — 1000 o'rniga qariyb 3,9 milliard. Xato xabari yo'q. Fayl yoki tarmoqdan "g'alati ulkan son" kelsa — birinchi gumon: bayt tartibi.
DataView da har tur uchun juft metodlar bor: getInt8/setInt8, getUint16/setUint16, getFloat32/setFloat32, getBigInt64 va boshqalar. Ularning hammasida tartib argumenti bir xil ishlaydi (bir baytlilardan tashqari — bitta baytda tartib yo'q).
Tekshirib ko'ring:
dv.setUint16(0, 0x0102)dan keyinnew Uint8Array(dv.buffer)ning birinchi ikki bayti qanday?setUint16(0, 0x0102, true)dan keyin-chi?
Javob
1, 2 — big-endian, katta qism (01) oldinda. true bilan — 2, 1. Son bir xil, faqat baytlar tartibi teskari.
7. Matn ↔ baytlar
7.1 TextEncoder va TextDecoder
Tarmoq orqali matn ham baytlar bo'lib ketadi. Matnni baytlarga aylantirish — kodlash (encoding). Bugungi standart — UTF-8. Unicode va emoji darsida ko'rgan edik: lotin harfi bitta joy egallaydi, boshqa belgilar ko'proq. UTF-8 da ham shunday:
const baytlar = new TextEncoder().encode("Osh ✓");
console.log(baytlar.length); // 7
console.log(new TextEncoder().encode("ош").length); // 4
console.log(new TextDecoder().decode(baytlar)); // Osh ✓"Osh" va bo'sh joy — 4 bayt, ✓ belgisi esa yolg'iz o'zi — 3 bayt. Kirill harflari 2 baytdan. TextEncoder doim UTF-8 da Uint8Array qaytaradi, TextDecoder esa teskarisini qiladi. Ikkalasi brauzerda ham, Node'da ham tayyor.
Shuning uchun "matn uzunligi" va "baytlar soni" — har xil narsa. Ma'lumotlar bazasida "255 bayt" chegarasi bo'lsa, 255 ta kirill harfi unga sig'maydi.
7.2 Hex va Base64
Baytlarni odam o'qiydigan matnga aylantirishning ikki mashhur usuli bor:
- Hex — har bayt ikki belgi:
89504e47. Xesh summalar, ranglar (#ff8800), fayl imzolari shunday yoziladi. - Base64 — baytlarni lotin harflari, raqamlar,
+va/bilan yozish. Email ilovalari,data:URL'lar, tokenlar shu ko'rinishda. Hex'dan ixchamroq: 3 bayt — 4 belgi.
Hex'ni o'zimiz yasay olamiz — tanish vositalar bilan:
const imzo = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
const hex = Array.from(imzo, (b) => b.toString(16).padStart(2, "0"));
console.log(hex.join("")); // 89504e47toString(16) — sonni o'n oltilik satrga (Sanoq tizimlari), padStart(2, "0") — bir xonali a ni 0a qiladi (Kesish va to'ldirish). Array.from oddiy massiv qaytaradi — typed array'ning map i satr qaytara olmasdi.
2025-yilda bu ishlar uchun tayyor metodlar qo'shildi (ES2026 standarti): toHex(), Uint8Array.fromHex(), toBase64(), Uint8Array.fromBase64(). Ular Chrome 140, Firefox 133 va Safari 18.2 da bor (Baseline ma'lumoti: "Baseline 2025", 2025-yil sentabr). Node 24 da hali yo'q — shuning uchun natija oynasida, brauzerda ko'ramiz. Konsol paneliga qarang:
<p>Konsolni oching: baytlar → hex → Base64 → baytlar.</p>
<script>
const imzo = new Uint8Array([0x89, 0x50, 0x4e, 0x47]);
console.log(imzo.toHex());
const salom = new TextEncoder().encode("Bahor");
const b64 = salom.toBase64();
console.log(b64);
const qaytgan = Uint8Array.fromBase64(b64);
console.log(new TextDecoder().decode(qaytgan));
console.log(Uint8Array.fromHex("0d0a").join(" "));
</script>Konsolda:
89504e47
QmFob3I=
Bahor
13 10"Bahor" so'zining 5 bayti Base64 da 8 belgi bo'ldi (oxiridagi = — to'ldiruvchi). fromBase64 uni aynan o'sha baytlarga qaytardi. Eski brauzerlarni ham qo'llash kerak bo'lsa — yuqoridagi qo'lda yozilgan hex funksiyasi yoki eski btoa/atob funksiyalari ishlatiladi.
Diqqat: Base64 — shifrlash emas. U faqat ko'rinishni o'zgartiradi, istalgan odam uni bir qator bilan ortga qaytaradi. Parolni "Base64 qildim, endi xavfsiz" deyish — jiddiy xato. Shifrlash — boshqa mavzu, uni xavfsizlik qismlarida ko'ramiz.
8. O'lchami o'zgaradigan va ko'chiriladigan xotira
Odatda ArrayBuffer ning hajmi yaratilganda qotadi. 2024-yildan boshlab ikki yangi imkoniyat bor (Baseline ma'lumoti: "Baseline 2024").
O'lchami o'zgaradigan (resizable) bufer. Yaratishda eng katta hajmni ko'rsatasiz, keyin resize bilan kattalashtirasiz yoki kichraytirasiz:
const xotira = new ArrayBuffer(2, { maxByteLength: 8 });
const baytlar = new Uint8Array(xotira);
console.log(baytlar.length); // 2
xotira.resize(6);
console.log(baytlar.length); // 6Typed array uzunlik bermasdan yaratilgani uchun u bufer bilan birga o'sdi. Fayl qismlari tarmoqdan asta-sekin kelganda qulay: har safar yangi bufer yaratib, eskisini ko'chirish shart emas.
Ko'chirish (transfer). transfer() xotirani yangi ArrayBuffer ga o'tkazadi — nusxa olmasdan. Eskisi esa bo'shab qoladi ("detached"):
const eski = new ArrayBuffer(4);
const korinish = new Uint8Array(eski);
korinish[0] = 7;
const yangi = eski.transfer();
console.log(eski.detached, eski.byteLength); // true 0
console.log(korinish.length); // 0
console.log(new Uint8Array(yangi)[0]); // 7Ma'lumot yangi ga o'tdi. eski va unga qaragan korinish endi bo'sh. Bu — "ushbu xotira endi menga tegishli emas" degan kafolat. Brauzerda katta ma'lumotni fon oqimiga yuborganda aynan shunday ko'chiriladi. Fon oqimi (Web Worker) — sahifa bilan yonma-yon ishlaydigan alohida skript; uni keyingi qismlarda o'rganamiz, hozir bilish shart emas.
9. Ko'p uchraydigan xatolar
9.1 push is not a function
Typed array uzunligi qat'iy. Tuzatish: kerakli uzunlikni oldindan biling yoki oddiy massivda yig'ib, oxirida new Uint8Array(massiv) qiling.
9.2 Jim toshish
Uint8Array ga 256 yozilsa — 0, map natijasi ham toshadi. Xato xabari yo'q. Tuzatish: sig'maydigan hisobni oddiy massivda qiling (Array.from(b, ...)), piksellar uchun — Uint8ClampedArray.
9.3 Bayt tartibi adashgan
Sonlar "g'alati ulkan" chiqsa — little/big-endian adashgan. Tuzatish: fayl yoki protokol hujjatidan tartibni toping va DataView ning oxirgi argumentini aniq yozing.
9.4 subarray ni nusxa deb o'ylash
subarray ga yozilgan narsa asl massivda ham o'zgaradi. Tuzatish: mustaqil nusxa kerak bo'lsa — slice.
9.5 Typed array'ni muzlatish
Oddiy obyekt va massivni o'zgarmas qilish usulini Obyektni himoyalash darsida o'rganamiz. Typed array'da u ishlamaydi:
Object.freeze(new Uint8Array(2));TypeError: Cannot freeze array buffer views with elementsTarjimasi: "elementli bufer ko'rinishlarini muzlatib bo'lmaydi". Baytlar xotirasi har doim o'zgaruvchan. O'zgarmasligi kerak bo'lsa — nusxasini bering (slice).
10. Mashqlar
1-mashq (oson): RGB rang
#ff8800 rangining uch qismini (qizil, yashil, ko'k) Uint8Array ga yozing va konsolga chiqaring. So'ng har qismga 100 qo'shib, natijani Uint8ClampedArray da hisoblang. Ishora: 0xff — hex son (Sanoq tizimlari); typed array'ning map i xuddi shu turni qaytaradi.
Yechim
const rang = new Uint8Array([0xff, 0x88, 0x00]);
console.log(rang); // Uint8Array(3) [ 255, 136, 0 ]
const yorugroq = new Uint8ClampedArray(rang).map((x) => x + 100);
console.log(yorugroq); // Uint8ClampedArray(3) [ 255, 236, 100 ]new Uint8ClampedArray(rang) — mavjud typed array'dan nusxa, boshqa turda. Qizil allaqachon 255 edi — chegarada qoldi. Uint8Array da map qilganimizda esa qizil 99 ga aylanib o'tardi (355 − 256).
2-mashq (o'rta): Tarozi xabari
«Bahor» oshxonasidagi elektron tarozi har o'lchovni 4 baytda yuboradi: grammdagi og'irlik, little-endian, ishorasiz butun son. Kelgan baytlar: [0x10, 0x27, 0x00, 0x00]. Og'irlikni DataView bilan o'qing. Ishora: new DataView(baytlar.buffer) va getUint32(0, true).
Yechim
const baytlar = new Uint8Array([0x10, 0x27, 0x00, 0x00]);
const dv = new DataView(baytlar.buffer);
console.log(dv.getUint32(0, true)); // 10000
console.log(dv.getUint32(0)); // 270991360To'g'ri tartibda — 10 000 gramm, ya'ni 10 kg guruch. Tartib adashsa — 270 million gramm. Ikkinchi qatorni ataylab qo'shdik: xato javob qanchalik "ishonchsiz" ko'rinishini eslab qoling.
3-mashq (qiyin): O'z hexdan funksiyangiz
hexdan(matn) funksiyasini yozing: "89504e47" kabi satrdan Uint8Array qaytarsin. Toq uzunlikdagi satr uchun bo'sh Uint8Array qaytarsin. So'ng natijani hex'ga qaytarib, asl satr bilan solishtiring. Ishora: ikki belgidan bitta bayt — Number.parseInt(qism, 16) (Matn ↔ son); Array.from({ length: n }, ...) — oldingi darsdan.
Yechim
function hexdan(matn) {
if (matn.length % 2 !== 0) {
return new Uint8Array(0);
}
const sonlar = Array.from({ length: matn.length / 2 }, (_, i) =>
Number.parseInt(matn.slice(i * 2, i * 2 + 2), 16),
);
return new Uint8Array(sonlar);
}
function hexga(baytlar) {
return Array.from(baytlar, (b) => b.toString(16).padStart(2, "0"))
.join("");
}
const baytlar = hexdan("89504e47");
console.log(baytlar); // Uint8Array(4) [ 137, 80, 78, 71 ]
console.log(hexga(baytlar) === "89504e47"); // true
console.log(hexdan("abc").length); // 0Array.from({ length: 4 }, ...) — har ikki belgi uchun bitta qadam. slice(i * 2, i * 2 + 2) — i-juftlikning ikki belgisi. Brauzerda yangi Uint8Array.fromHex ham bor, lekin u noto'g'ri satrda xato tashlaydi — biz esa bo'sh natija qaytarishni tanladik. Bu — funksiya "shartnomasi": noto'g'ri kirishda nima bo'lishini siz hal qilasiz.
4-mashq: Mashqlar qadami — fayl imzosini aniqlash
Bu mavzu ham vazifalar ga tegmaydi — qadam mashqlar reposida. kurs/mashqlar/10/11-baytlar/imzo.js faylini yarating.
faylTuri(baytlar) funksiyasini yozing. U Uint8Array oladi va birinchi baytlariga qarab tur nomini qaytaradi:
| Tur | Boshidagi baytlar (hex) |
|---|---|
"png" |
89 50 4e 47 |
"jpeg" |
ff d8 ff |
"pdf" |
25 50 44 46 (bu — %PDF matni) |
Boshqa holatda — "noma'lum". Uch to'g'ri va ikki "noto'g'ri" holatni sinang: bo'sh Uint8Array va faqat ikki baytli fayl.
Yechim
const imzolar = [
{ tur: "png", baytlar: [0x89, 0x50, 0x4e, 0x47] },
{ tur: "jpeg", baytlar: [0xff, 0xd8, 0xff] },
{ tur: "pdf", baytlar: new TextEncoder().encode("%PDF") },
];
function boshlanadimi(baytlar, imzo) {
if (baytlar.length < imzo.length) {
return false;
}
return Array.from(imzo).every((b, i) => baytlar[i] === b);
}
function faylTuri(baytlar) {
const topildi = imzolar.find(
(x) => boshlanadimi(baytlar, x.baytlar),
);
return topildi ? topildi.tur : "noma'lum";
}
const sinovlar = [
new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a]),
new Uint8Array([0xff, 0xd8, 0xff, 0xe0]),
new TextEncoder().encode("%PDF-1.7"),
new Uint8Array(0),
new Uint8Array([0x89, 0x50]),
];
for (const baytlar of sinovlar) {
console.log(faylTuri(baytlar));
}Konsolda:
png
jpeg
pdf
noma'lum
noma'lumPDF imzosini hex bilan emas, TextEncoder bilan yozdik — chunki u aynan %PDF matni. boshlanadimi dagi uzunlik tekshiruvi muhim: usiz ikki baytli fayl uchun baytlar[2] — undefined, taqqoslash false beradi va natija to'g'ri chiqadi, lekin tasodifan. Shartni ochiq yozish — niyatni ko'rsatadi.
Ishga tushiring va commit qiling:
cd ~/kurs/mashqlar
node 10/11-baytlar/imzo.js
git add 10/11-baytlar
git commit -m "10/11: fayl imzosini baytlardan aniqlashni qo'sh"11. Real ishda
- Fayl yuklash va xavfsizlik. Saytga rasm yuklanganda server faqat nomdagi
.pngga ishonmaydi — 4-mashqdagi kabi birinchi baytlarni tekshiradi. Hujumchivirus.exenirasm.pngdeb nomlashi mumkin, baytlar esa yolg'on gapirmaydi. - Brauzer API'lari.
fetchjavobiningarrayBuffer(), fayl o'qish,<canvas>piksellari (Uint8ClampedArray), WebSocket'dagi binar xabarlar, Web Audio ovoz to'lqinlari — hammasi typed array. Ularni keyingi qismlarda ko'rasiz. - Node.js. Node'dagi
Buffer—Uint8Arrayning "kengaytirilgan" turi. Fayllar, tarmoq, shifrlash — hammasi u orqali (Node.js qismi). - Sun'iy intellekt va grafika. Model og'irliklari va 3D nuqtalar
Float32Array/Float16Arrayda saqlanadi — millionlab son bitta ixcham xotirada. - Intervyu. "
ArrayBufferva typed array farqi?", "endianness nima?", "Base64 shifrlashmi?" — backend va frontend intervyularida uchraydi.
Xulosa
- Typed array — bir xil turdagi sonlar uchun qat'iy o'lchamli massiv:
Uint8Array,Int32Array,Float64Array,Float16Array. - Butun turlar toshadi (256 → 0),
Uint8ClampedArraychegarada to'xtaydi; kasr turlari aniqlikni xotira evaziga yo'qotadi. ArrayBuffer— xom xotira; typed array vaDataView— unga qaraydigan ko'rinishlar.subarrayxotirani bo'lishadi,slicenusxalaydi.- Ko'p baytli son tartibi — endianness; tashqi ma'lumotni
DataViewbilan tartibni aniq ko'rsatib o'qing. TextEncoder/TextDecoder— matn ↔ UTF-8 baytlar;toHex/toBase64— yangi (ES2026) tayyor metodlar, Base64 shifrlash emas.
Keyingi dars: Getter va setter — obyektlarga qaytamiz: o'qilganda hisoblanadigan va yozilganda tekshiriladigan xususiyatlar yasaymiz.
Manbalar
- MDN: "JavaScript typed arrays", "ArrayBuffer", "DataView", "Float16Array" — developer.mozilla.org
- MDN: "Uint8Array.prototype.toHex()", "Uint8Array.fromBase64()" — developer.mozilla.org
- web-features 3.40.0:
float16array,uint8array-base64-hex,resizable-buffers,transferable-arraybuffer - ECMAScript 2026 Language Specification: "TypedArray Objects", "ArrayBuffer Objects" — tc39.es/ecma262
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!