ArrayBuffer i TypeScript
Den här artikeln förklarar ArrayBuffer i TypeScript.
Vi förklarar ArrayBuffer i TypeScript steg för steg, från grunderna till praktiska tekniker.
YouTube Video
ArrayBuffer i TypeScript
ArrayBuffer är ett inbyggt objekt som representerar ett "rått minnesområde" för binärdata. Det representerar en rå buffert med fast längd, ovanpå vilken TypedArray eller DataView kan läggas för läsning och skrivning.
Grundläggande begrepp och egenskaper för ArrayBuffer
ArrayBuffer är en byte-sekvens med fast längd. Du anger storleken i byte när du skapar den, och dess längd kan inte ändras efteråt.
1// Create a new ArrayBuffer of 16 bytes.
2const buf = new ArrayBuffer(16);
3console.log(buf.byteLength); // 16
- Den här koden skapar en tom buffert med 16 byte. Du kan kontrollera storleken med hjälp av
byteLength.
TypedArray och DataView — vyer för att hantera buffertar
ArrayBuffer har inte möjligheten att läsa eller skriva data. Därför utförs faktiska operationer via TypedArray eller DataView, där man anger typer som heltal eller flyttal samt ändlighet vid åtkomst till data.
1// Create a buffer and a Uint8Array view over it. Then write bytes and read them.
2const buffer = new ArrayBuffer(8);
3const u8 = new Uint8Array(buffer);
4
5u8[0] = 0x41; // 'A'
6u8[1] = 0x42; // 'B'
7console.log(u8); // Uint8Array(8) [ 65, 66, 0, 0, 0, 0, 0, 0 ]
Uint8Arrayär en vy över arrayen per byte och kan användas på samma sätt som en vanlig array. Om du lägger flera vyer på sammaArrayBufferdelar de minne för läsning och skrivning.
DataView: Läsning och skrivning vid godtyckliga gränser och med valfri byteordning
DataView är användbart för detaljerad läsning och skrivning per byte, och låter dig ange little-endian eller big-endian.
1// Using DataView to write/read multi-byte values with endianness control.
2const buf2 = new ArrayBuffer(8);
3const view = new DataView(buf2);
4
5// Write a 32-bit integer (little-endian)
6view.setInt32(0, 0x12345678, true);
7
8// Read it back as little-endian and big-endian
9const little = view.getInt32(0, true);
10const big = view.getInt32(0, false);
11console.log(little.toString(16)); // "12345678"
12console.log(big.toString(16)); // "78563412"
DataViewlåter dig läsa och skriva värden genom att ange offset i minnet, vilket gör det lämpligt för implementering av protokoll som kräver hantering av nätverksbyteordning.
Konvertering mellan strängar och ArrayBuffer (TextEncoder / TextDecoder)
För att konvertera text till binär och tvärtom, använd TextEncoder och TextDecoder.
1// Convert string -> ArrayBuffer and back using TextEncoder/TextDecoder.
2const encoder = new TextEncoder();
3const decoder = new TextDecoder();
4
5// Unicode escape sequences
6const str = "\u3053\u3093\u306B\u3061\u306F";
7const encoded = encoder.encode(str); // Uint8Array
8console.log(encoded); // Uint8Array([...])
9
10// If you need an ArrayBuffer specifically:
11const ab = encoded.buffer.slice(encoded.byteOffset, encoded.byteOffset + encoded.byteLength);
12console.log(ab.byteLength); // bytes length of encoded text
13
14// Decode back
15const decoded = decoder.decode(encoded);
16console.log(decoded);TextEncoder.encodereturnerar enUint8Array, så om du behöver enArrayBufferbör du använda dess.buffer-egenskap. Medslice-metoden kan du extrahera den nödvändiga datan genom att ange offset och längd.
Dela och kopiera ArrayBuffer
slice-metoden returnerar en ny ArrayBuffer. ArrayBuffer kan inte ändra storlek; om storleksändring är nödvändig, skapa en ny buffert och kopiera in datan.
1// Slice an ArrayBuffer and copy to a new sized buffer.
2const original = new Uint8Array([1,2,3,4,5]).buffer;
3const part = original.slice(1, 4); // bytes 1..3
4console.log(new Uint8Array(part)); // Uint8Array [ 2, 3, 4 ]
5
6// Resize: create a new buffer and copy existing content
7const larger = new ArrayBuffer(10);
8const target = new Uint8Array(larger);
9target.set(new Uint8Array(original), 0);
10console.log(target); // first bytes filled with original data
- Eftersom
slice-metoden returnerar en nyArrayBuffer, kan du, om du prioriterar effektivitet eller delning av referenser, användasubarray-metoden förTypedArrayför att referera till samma buffert.
Skillnad mellan TypedArray.subarray och kopiering
TypedArray's subarray returnerar en ny vy som hänvisar till samma ArrayBuffer.
1// subarray shares the same underlying buffer; modifying one affects the other.
2const arr = new Uint8Array([10,20,30,40]);
3const viewSub = arr.subarray(1,3); // shares memory
4viewSub[0] = 99;
5console.log(arr); // Uint8Array [10, 99, 30, 40]
- Delade vyer kan undvika kopieringskostnader, men eftersom de refererar till samma buffert måste du vara försiktig med bieffekter.
Sammanfogning av buffertar (kombinera flera ArrayBuffers)
Eftersom ArrayBuffer har fast längd, skapa en ny ArrayBuffer och kopiera data för att kombinera flera buffertar.
1// Concatenate multiple ArrayBuffers
2function concatBuffers(buffers: ArrayBuffer[]): ArrayBuffer {
3 const total = buffers.reduce((sum, b) => sum + b.byteLength, 0);
4 const result = new Uint8Array(total);
5 let offset = 0;
6 for (const b of buffers) {
7 const u8 = new Uint8Array(b);
8 result.set(u8, offset);
9 offset += u8.length;
10 }
11 return result.buffer;
12}
13
14const a = new Uint8Array([1,2]).buffer;
15const b = new Uint8Array([3,4,5]).buffer;
16const c = concatBuffers([a, b]);
17console.log(new Uint8Array(c)); // [1,2,3,4,5]
- Om du ofta slår samman stora mängder data är det mer effektivt att förberäkna den totala storleken och allokera en ny buffert endast en gång, som i denna kod.
Skicka ArrayBuffer till en Worker (Transferable)
I webbläsarens postMessage kan du överföra en ArrayBuffer som ett "överförbart" objekt. Ägarskap kan överföras utan kopiering, vilket undviker kopieringskostnaden.
1// Example: posting an ArrayBuffer to a Worker as a transferable object (browser)
2const worker = new Worker('worker.js');
3const bufferToSend = new Uint8Array([1,2,3,4]).buffer;
4
5// Transfer ownership to the worker (main thread no longer owns it)
6worker.postMessage(bufferToSend, [bufferToSend]);
7
8// After transfer, bufferToSend.byteLength === 0 in many browsers (detached)
9console.log(bufferToSend.byteLength); // may be 0
- Genom att ange objekten som ska överföras i en array som det andra argumentet till
postMessagekan du överföra ägarskapet av överförbara objekt somArrayBufferutan kopiering. - Efter överföringen blir bufferten "frånkopplad" på den ursprungliga sidan och kan inte nås. Användning av
SharedArrayBuffermöjliggör samtida åtkomst från flera trådar, men dess användning har säkerhetskrav och miljörestriktioner.
Hantering i Node.js (konvertering till/från Buffer)
I Node.js kan du konvertera mellan Node.js binära typ Buffer och ArrayBuffer. Detta är användbart när du riktar dig mot både webbläsare och Node.js med TypeScript.
1// Convert ArrayBuffer <-> Node.js Buffer
2// In Node.js environment:
3const ab = new Uint8Array([10,20,30]).buffer;
4const nodeBuffer = Buffer.from(ab); // ArrayBuffer -> Buffer
5console.log(nodeBuffer); // <Buffer 0a 14 1e>
6
7const backToAb = nodeBuffer.buffer.slice(
8 nodeBuffer.byteOffset,
9 nodeBuffer.byteOffset + nodeBuffer.byteLength
10);
11console.log(new Uint8Array(backToAb)); // Uint8Array [10,20,30]
Buffer.from(arrayBuffer)i Node.js skapar vanligtvis en kopia, men det finns fall där referensdelning är möjlig, så var uppmärksam på offset.
Prestandahänsyn och bästa praxis
För att optimera prestanda och hantera ArrayBuffer effektivt finns det flera viktiga punkter att tänka på. Nedan listar och förklarar vi praktiska bästa praxis.
-
Minska antalet kopior Vid hantering av stora binära data, använd
subarray(delad vy) eller transferables för att minska antalet kopior. -
Allokera stora buffertar på en gång Att upprepade gånger allokera små buffertar ökar overheaden. Om möjligt, allokera en stor buffert på en gång och använd delar av den vid behov.
-
Ange ändianness uttryckligen När du hanterar flerbytevärden, använd
DataViewoch ange byteordningen explicit. Big-endian är ofta standard för nätverksprotokoll.
Vanliga användningsfall
ArrayBuffer används ofta både i webbläsare och i Node.js.
- Tolkar och bygger binära protokoll (behandlar headerinformation med
DataView) - Mediabehandling som bild- och ljuddata (
fetch(...).then(res => res.arrayBuffer())) - Delat minne för WebAssembly (Wasm-minne fungerar baserat på
ArrayBuffer) - Avlastning av tung bearbetning till Workers (skicka
ArrayBuffersom transferable)
Följande kod är ett exempel på att hämta och analysera binärdata.
1// Example: fetch binary data in browser and inspect first bytes
2async function fetchAndInspect(url: string) {
3 const resp = await fetch(url);
4 const ab = await resp.arrayBuffer();
5 const u8 = new Uint8Array(ab, 0, Math.min(16, ab.byteLength));
6 console.log('first bytes:', u8);
7}- Den här koden hämtar binärdata från en valfri URL i webbläsaren och visar de första byten. Koden laddar data som hämtats via
fetchAPI som enArrayBufferoch inspekterar de första 16 byten med enUint8Array.
Sammanfattning
ArrayBuffer är en rå minnesrepresentation som möjliggör effektiva binära operationer via TypedArray och DataView. Genom att utforma så att onödig kopiering undviks och endianness anges explicit kan du uppnå säker och högpresterande binärbearbetning.
Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.