TypedArray i TypeScript
Denne artikkelen forklarer TypedArray i TypeScript.
Vi skal forklare TypedArray i TypeScript, inkludert praktiske eksempler.
YouTube Video
TypedArray i TypeScript
TypedArray er en mekanisme for effektiv håndtering av binærdata. Det er spesielt nyttig for lavnivå binæroperasjoner som store bildedata, nettverksbytestømmer og numeriske matriser for WebGL.
Hvordan opprette en ArrayBuffer
ArrayBuffer representerer et område av byte med fast lengde. Først oppretter du en buffer og sjekker størrelsen og bytelengden.
1// Create an ArrayBuffer of 16 bytes
2const buffer: ArrayBuffer = new ArrayBuffer(16);
3console.log("buffer.byteLength:", buffer.byteLength); // 16
- Denne koden oppretter et tomt område på 16 byte.
ArrayBufferhar ikke egne lese/skriv-funksjoner, så du må aksessere den gjennomTypedArrayellerDataView.
Typer av TypedArray
Det finnes mange typer TypedArray, som for eksempel følgende. Disse varierer avhengig av datatypen og størrelsen de håndterer.
| TypedArray | Datatype | Bitstørrelse |
|---|---|---|
Int8Array |
8-bit heltall | 8 biter |
Uint8Array |
Uten fortegn 8-bit heltall | 8 biter |
Uint8ClampedArray |
Begrenset uten fortegn 8-bit heltall | 8 biter |
Int16Array |
16-bit heltall | 16 biter |
Uint16Array |
Uten fortegn 16-bit heltall | 16 biter |
Int32Array |
32-bit heltall | 32 biter |
Uint32Array |
Uten fortegn 32-bit heltall | 32 biter |
Float32Array |
32-bits flyttall | 32 biter |
Float64Array |
64-bits flyttall | 64 biter |
Grunnleggende TypedArrays (Uint8Array, Int16Array, Float32Array, osv.)
TypedArray oppretter en 'typet visning' på toppen av en ArrayBuffer. Her er eksempler på hvordan man oppretter og bruker noen typiske TypedArrays.
1// Create a buffer and different typed views over it
2const buf = new ArrayBuffer(8); // 8 bytes
3
4// Create views
5const u8 = new Uint8Array(buf); // 8 x uint8
6const i16 = new Int16Array(buf); // 4 x int16 (since each int16 is 2 bytes)
7const f32 = new Float32Array(buf); // 2 x float32 (4 bytes each)
8
9console.log("Uint8 length:", u8.length);
10console.log("Int16 length:", i16.length);
11console.log("Float32 length:", f32.length);- Ved å lage flere visninger på samme
ArrayBufferkan du lese og skrive den samme minnet med forskjellige typer eller granulariteter.lengthfor visningen er antall elementer, ogbyteLengther antall byte.
Skriving og lesing (byte-nivå operasjoner)
Når du skriver en verdi til en TypedArray, blir de tilsvarende bytene i minnet oppdatert. Du kan se endringene når du leser den samme bufferen med en annen visning.
1// Demonstrate writing via one view and reading via another
2const buffer2 = new ArrayBuffer(4);
3const u8view = new Uint8Array(buffer2);
4const u32view = new Uint32Array(buffer2);
5
6u8view[0] = 0x78;
7u8view[1] = 0x56;
8u8view[2] = 0x34;
9u8view[3] = 0x12;
10
11console.log("Uint8 bytes:", Array.from(u8view)); // [120, 86, 52, 18]
12console.log("Uint32 value (platform endianness):", u32view[0]); // value depends on endianness
- I dette eksemplet skriver vi en bytesevens og leser så det samme området som et 32-bits heltall. Merk at utdataene avhenger av endianness i kjøringsmiljøet.
Endianness (byte-rekkefølge) og DataView
DataView er nyttig hvis du vil kontrollere miljøavhengige problemer med endianness. DataView lar deg spesifisere sluttianitet (endianness) når du leser og skriver.
1// Use DataView to read/write with explicit endianness control
2const b = new ArrayBuffer(4);
3const dv = new DataView(b);
4
5// write little-endian 32-bit integer
6dv.setUint32(0, 0x12345678, true);
7
8// read as little-endian and big-endian
9const little = dv.getUint32(0, true);
10const big = dv.getUint32(0, false);
11
12console.log("little-endian read:", little.toString(16)); // "12345678"
13console.log("big-endian read:", big.toString(16)); // different value
DataViewer en praktisk mekanisme for detaljert lesing og skriving av byte. Den støtter ulike typer, som signerte og usignerte heltall samt flyttall, og lar deg eksplisitt spesifisere endianness (byte-rekkefølge), noe som er svært nyttig når du implementerer binære protokoller.
Forskjell mellom subarray og slice
subarray av en TypedArray returnerer en visning som deler den opprinnelige bufferen, mens slice returnerer en ny kopi. Ytelse og bivirkninger varierer avhengig av hvilken du bruker.
1const base = new Uint8Array([1, 2, 3, 4, 5]);
2
3const shared = base.subarray(1, 4); // shares underlying buffer
4const copied = base.slice(1, 4); // copies data
5
6shared[0] = 99;
7console.log("base after shared modification:", base); // shows change
8console.log("copied remains:", copied); // unaffected
- Hvis du endrer den delte visningen, vil den opprinnelige matrisen også endres, noe som kan føre til utilsiktede bivirkninger. Hvis du vil bevare den opprinnelige matrisen trygt, kan du opprette en kopi på forhånd ved å bruke
slice().
Kopiering av buffere og typekonvertering (konvertering mellom TypedArrays)
Vi forklarer hvordan du kopierer data mellom TypedArrays og hvordan du limer inn deler ved hjelp av set-metoden.
1// Copy and convert between typed arrays
2const src = new Float32Array([1.5, 2.5, 3.5]);
3const dst = new Uint16Array(src.length);
4
5// Convert by mapping (explicit conversion)
6for (let i = 0; i < src.length; i++) {
7 dst[i] = Math.round(src[i]); // simple conversion rule
8}
9console.log("converted dst:", Array.from(dst)); // [2, 2, 4]
10
11// Using set to copy bytes (requires compatible underlying buffer or same element type)
12const src2 = new Uint8Array([10, 20, 30]);
13const dst2 = new Uint8Array(6);
14dst2.set(src2, 2); // copy src2 into dst2 starting at index 2
15console.log("dst2 after set:", Array.from(dst2)); // [0,0,10,20,30,0]
- Hvis elementtypene er forskjellige, må du konvertere verdiene, for eksempel ved avrunding eller områdekontroll, i stedet for bare å kopiere.
setgjør det mulig å raskt kopiere mellomTypedArrays av samme elementtype.
Praktisk eksempel: En binær protokollparser (enkel implementasjon)
Her introduserer vi et enkelt parser-eksempel som leser binærdata med fast format, bestående av en 1-byte type, 2-byte datalengde, og en påfølgende payload.
1// Simple binary message parser:
2// format: [type: uint8][length: uint16 BE][payload: length bytes]
3function parseMessages(buffer: ArrayBuffer) {
4 const dv = new DataView(buffer);
5 let offset = 0;
6 const messages: { type: number; payload: Uint8Array }[] = [];
7
8 while (offset + 3 <= dv.byteLength) {
9 const type = dv.getUint8(offset);
10 const length = dv.getUint16(offset + 1, false); // big-endian
11 offset += 3;
12 if (offset + length > dv.byteLength) break; // truncated
13 const payload = new Uint8Array(buffer, offset, length);
14 messages.push({ type, payload });
15 offset += length;
16 }
17
18 return messages;
19}
20
21// Example usage
22const buf = new ArrayBuffer(1 + 2 + 3 + 1 + 2 + 2); // two messages
23const dv = new DataView(buf);
24let off = 0;
25// first message: type=1, length=3, payload=[1,2,3]
26dv.setUint8(off, 1); dv.setUint16(off + 1, 3, false); off += 3;
27new Uint8Array(buf, off, 3).set([1, 2, 3]); off += 3;
28// second message: type=2, length=2, payload=[9,8]
29dv.setUint8(off, 2); dv.setUint16(off + 1, 2, false); off += 3;
30new Uint8Array(buf, off, 2).set([9, 8]);
31
32console.log(parseMessages(buf));- I dette eksemplet leses headeren ved hjelp av
DataView, og nyttelast-delen opprettes medUint8Array. Endianness og bufferlengdekontroll er viktig.
Web-API og TypedArray (Eksempel: hente binærdata)
Dette er et typisk eksempel på å håndtere en ArrayBuffer hentet fra en nettverksforespørsel ved hjelp av TypedArray.
1// Example of fetching binary and mapping to typed array
2async function fetchBinary(url: string) {
3 const res = await fetch(url);
4 const ab = await res.arrayBuffer();
5 const view = new Uint8Array(ab);
6 // process view...
7 console.log("received bytes:", view.length);
8 return view;
9}
10
11// Usage (call in async context)
12// fetchBinary("/path/to/file.bin");
- Du kan sende
ArrayBufferoppnådd medResponse.arrayBuffer()direkte til enTypedArray. Det brukes for bilder, lyd eller egendefinerte binære protokoller.
Ytelsestips og vanlige fallgruver
Her er noen 'ytelsestips' og 'vanlige fallgruver' som det er nyttig å kjenne til når du bruker TypedArrays:.
-
Unngå unødvendig kopiering For å håndtere store datamengder effektivt, kan du redusere unødvendig kopiering ved å lage delvisninger med
subarrayeller dele sammeArrayBufferpå tvers av flere visninger. -
Vær oppmerksom på endianness For nettverkskommunikasjon eller filformater er rekkefølgen på dataene (byterekkefølge) ofte spesifisert. Ved å bruke
DataViewkan du eksplisitt angi endianness ved lesing og skriving, og dermed unngå feil tolkning. -
Vær oppmerksom på verdiområdet for hver type For eksempel kan
Uint8bare representere verdier fra 0 til 255. Hvis du oppgir en negativ verdi, kan det oppstå avkutting eller verdi-overløp, så du bør definere konverteringsregler etter behov. -
Vurder belastningen på søppelinnsamling (garbage collection) Hyppig gjenskaping av store
ArrayBuffer-objekter øker belastningen på minnehåndteringen. I ytelseskritiske situasjoner kan det være lurt å utforme koden slik at eksisterende buffere gjenbrukes så mye som mulig.
Sammendrag
TypedArray er en mekanisme for rask og effektiv håndtering av binærdata. Ved å kombinere ArrayBuffer, som reserverer et byteområde med fast lengde, med TypedArray eller DataView, som leser og skriver innholdet med bestemte typer, kan du utføre fleksible binæroperasjoner. Avhengig av bruken din kan du velge mellom å bruke subarray/slice eller DataView, og utforme implementasjonen din med hensyn til endianness og kopier.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.