ArrayBuffer KonstruktorArrayBuffer MethodenArrayBuffer.prototype EigenschaftenTypedArray MethodenTypedArray.prototype Eigenschaften«ElementType»Array Konstruktor«ElementType»Array Eigenschaften«ElementType»Array.prototype EigenschaftenDataView KonstruktorDataView.prototype EigenschaftenXMLHttpRequestTyped Arrays sind eine ECMAScript 6 API zur Verarbeitung von Binärdaten.
Code-Beispiel
const typedArray = new Uint8Array([0,1,2]);
console.log(typedArray.length); // 3
typedArray[0] = 5;
const normalArray = [...typedArray]; // [5,1,2]
// The elements are stored in typedArray.buffer.
// Get a different view on the same data:
const dataView = new DataView(typedArray.buffer);
console.log(dataView.getUint8(0)); // 5
Instanzen von ArrayBuffer speichern die zu verarbeitenden Binärdaten. Zwei Arten von *Views* werden verwendet, um auf die Daten zuzugreifen:
Uint8Array, Int16Array, Float32Array usw.) interpretieren den ArrayBuffer als indizierte Sequenz von Elementen eines einzelnen Typs.DataView ermöglichen den Zugriff auf Daten als Elemente verschiedener Typen (Uint8, Int16, Float32 usw.) an jedem beliebigen Byte-Offset innerhalb eines ArrayBuffers.Die folgenden Browser-APIs unterstützen Typed Arrays (Details sind in einem eigenen Abschnitt aufgeführt).
Viele Daten, denen man im Web begegnet, sind Text: JSON-Dateien, HTML-Dateien, CSS-Dateien, JavaScript-Code usw. Für die Verarbeitung solcher Daten ist der integrierte String-Datentyp von JavaScript gut geeignet. Bis vor wenigen Jahren war JavaScript jedoch schlecht für die Verarbeitung von Binärdaten ausgestattet. Am 8. Februar 2011 standardisierte die Typed Array Specification 1.0 Einrichtungen für die Verarbeitung von Binärdaten. Mittlerweile werden Typed Arrays von verschiedenen Engines gut unterstützt. Mit ECMAScript 6 wurden sie Teil der Kernsprache und erhielten dabei viele Methoden, die zuvor nur für Arrays verfügbar waren (map(), filter() usw.).
Die Hauptanwendungsfälle für Typed Arrays sind:
Zwei Arten von Objekten arbeiten in der Typed Array API zusammen:
ArrayBuffer enthalten die Binärdaten.Uint8Array, Float64Array usw.) verhält sich ähnlich wie ein normales Array, erlaubt aber nur einen einzigen Datentyp für seine Elemente und hat keine Lücken.DataView ermöglicht den Zugriff auf Daten an jedem Byte-Offset im Puffer und interpretiert diese Daten als einen von mehreren Typen (Uint8, Float64 usw.).Dies ist ein Diagramm der Struktur der Typed Array API (bemerkenswert: alle Typed Arrays haben eine gemeinsame Oberklasse).
Die folgenden Elementtypen werden von der API unterstützt:
| Elementtyp | Bytes | Beschreibung | C-Typ |
|---|---|---|---|
| Int8 | 1 | 8-Bit vorzeichenbehafteter Integer | signed char |
| Uint8 | 1 | 8-Bit vorzeichenloser Integer | unsigned char |
| Uint8C | 1 | 8-Bit vorzeichenloser Integer (begrenzte Konvertierung) | unsigned char |
| Int16 | 2 | 16-Bit vorzeichenbehafteter Integer | short |
| Uint16 | 2 | 16-Bit vorzeichenloser Integer | unsigned short |
| Int32 | 4 | 32-Bit vorzeichenbehafteter Integer | int |
| Uint32 | 4 | 32-Bit vorzeichenloser Integer | unsigned int |
| Float32 | 4 | 32-Bit Gleitkommazahl | float |
| Float64 | 8 | 64-Bit Gleitkommazahl | double |
Der Elementtyp Uint8C ist besonders: Er wird nicht von DataView unterstützt und existiert nur, um Uint8ClampedArray zu ermöglichen. Dieser Typed Array wird vom canvas-Element verwendet (wo er CanvasPixelArray ersetzt). Der einzige Unterschied zwischen Uint8C und Uint8 liegt darin, wie Über- und Unterläufe behandelt werden (wie im nächsten Abschnitt erklärt). Es wird empfohlen, ersteren zu vermeiden – Zitat von Brendan Eich
Nur um ganz klar zu sein (und ich war dabei, als es geboren wurde),
Uint8ClampedArrayist *absolut* ein historisches Artefakt (des HTML5 Canvas-Elements). Vermeiden Sie es, es sei denn, Sie arbeiten wirklich mit Canvas-artigen Dingen.
Normalerweise wird beim Überschreiten des Wertebereichs des Elementtyps eine Modulo-Arithmetik verwendet, um ihn in einen Wert innerhalb des Bereichs zu konvertieren. Für vorzeichenbehaftete und vorzeichenlose Integer bedeutet dies, dass:
Modulo-Konvertierung für vorzeichenlose 8-Bit-Integer
> const uint8 = new Uint8Array(1);
> uint8[0] = 255; uint8[0] // highest value within range
255
> uint8[0] = 256; uint8[0] // overflow
0
> uint8[0] = 0; uint8[0] // lowest value within range
0
> uint8[0] = -1; uint8[0] // underflow
255
Modulo-Konvertierung für vorzeichenbehaftete 8-Bit-Integer
> const int8 = new Int8Array(1);
> int8[0] = 127; int8[0] // highest value within range
127
> int8[0] = 128; int8[0] // overflow
-128
> int8[0] = -128; int8[0] // lowest value within range
-128
> int8[0] = -129; int8[0] // underflow
127
Die begrenzte Konvertierung ist anders:
> const uint8c = new Uint8ClampedArray(1);
> uint8c[0] = 255; uint8c[0] // highest value within range
255
> uint8c[0] = 256; uint8c[0] // overflow
255
> uint8c[0] = 0; uint8c[0] // lowest value within range
0
> uint8c[0] = -1; uint8c[0] // underflow
0
Immer wenn ein Typ (wie Uint16) als mehrere Bytes gespeichert wird, spielt die *Endianness* eine Rolle:
Uint16-Wert 0xABCD als zwei Bytes gespeichert – zuerst 0xAB, dann 0xCD.Uint16-Wert 0xABCD als zwei Bytes gespeichert – zuerst 0xCD, dann 0xAB.Die Endianness ist typischerweise pro CPU-Architektur festgelegt und über native APIs hinweg konsistent. Typed Arrays werden zur Kommunikation mit diesen APIs verwendet, weshalb ihre Endianness der Endianness der Plattform folgt und nicht geändert werden kann.
Andererseits variiert die Endianness von Protokollen und Binärdateien und ist plattformübergreifend festgelegt. Daher müssen wir in der Lage sein, Daten mit beiden Endianness-Arten zu lesen. DataViews dienen diesem Zweck und ermöglichen es Ihnen, die Endianness beim Abrufen oder Festlegen eines Werts anzugeben.
Zitat von Wikipedia über Endianness:
Sie können die folgende Funktion verwenden, um die Endianness einer Plattform zu bestimmen.
const BIG_ENDIAN = Symbol('BIG_ENDIAN');
const LITTLE_ENDIAN = Symbol('LITTLE_ENDIAN');
function getPlatformEndianness() {
const arr32 = Uint32Array.of(0x12345678);
const arr8 = new Uint8Array(arr32.buffer);
switch ((arr8[0]*0x1000000) + (arr8[1]*0x10000) + (arr8[2]*0x100) + (arr8\
[3])) {
case 0x12345678:
return BIG_ENDIAN;
case 0x78563412:
return LITTLE_ENDIAN;
default:
throw new Error('Unknown endianness');
}
}
Es gibt auch Plattformen, die *Wörter* (Byte-Paare) mit einer anderen Endianness als Bytes innerhalb von Wörtern anordnen. Dies wird als gemischte Endianness bezeichnet. Sollten Sie eine solche Plattform unterstützen wollen, lässt sich der obige Code leicht erweitern.
Mit dem Klammeroperator [ ] können nur nicht-negative Indizes (beginnend bei 0) verwendet werden. Die Methoden von ArrayBuffers, Typed Arrays und DataViews verhalten sich anders: Jeder Index kann negativ sein. Wenn er negativ ist, zählt er rückwärts von der Länge. Mit anderen Worten, er wird zur Länge addiert, um einen normalen Index zu erzeugen. Daher bezieht sich -1 auf das letzte Element, -2 auf das vorletzte usw. Methoden normaler Arrays verhalten sich genauso.
> const ui8 = Uint8Array.of(0, 1, 2);
> ui8.slice(-1)
Uint8Array [ 2 ]
Offsets hingegen müssen nicht-negativ sein. Wenn Sie zum Beispiel -1 an
DataView.prototype.getInt8(byteOffset)
übergeben, erhalten Sie einen RangeError.
ArrayBuffers speichern die Daten, *Views* (Typed Arrays und DataViews) erlauben Ihnen, diese zu lesen und zu ändern. Um eine DataView zu erstellen, müssen Sie deren Konstruktor einen ArrayBuffer übergeben. Typed Array-Konstruktoren können optional einen ArrayBuffer für Sie erstellen.
ArrayBuffer Konstruktor Die Signatur des Konstruktors lautet:
ArrayBuffer(length : number)
Die Ausführung dieses Konstruktors über new erzeugt eine Instanz mit einer Kapazität von length Bytes. Jedes dieser Bytes ist anfänglich 0.
ArrayBuffer Methoden ArrayBuffer.isView(arg)true zurück, wenn arg ein Objekt und eine View für einen ArrayBuffer ist. Nur Typed Arrays und DataViews haben den erforderlichen internen Slot [[ViewedArrayBuffer]]. Das bedeutet, dass diese Prüfung ungefähr gleichwertig damit ist, zu prüfen, ob arg eine Instanz eines Typed Arrays oder von DataView ist.ArrayBuffer.prototype Eigenschaften get ArrayBuffer.prototype.byteLengthArrayBuffer.prototype.slice(start, end)start und kleiner als end sind. start und end können negativ sein (siehe Abschn. „Negative Indizes“).Die verschiedenen Arten von Typed Arrays unterscheiden sich nur hinsichtlich des Typs ihrer Elemente.
Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32ArrayFloat32Array, Float64ArrayTyped Arrays sind normalen Arrays sehr ähnlich: Sie haben eine length, Elemente können über den Klammeroperator [ ] abgerufen werden und sie verfügen über alle Standard-Array-Methoden. Sie unterscheiden sich von Arrays in folgenden Punkten:
arr.length), die keinem Element zugeordnet sind), Typed Arrays können das nicht.new Array(10) erstellt ein normales Array ohne Elemente (es hat nur Lücken).new Uint8Array(10) erstellt ein Typed Array, dessen 10 Elemente alle 0 sind.ta werden nicht in ta gespeichert, sondern in einem zugehörigen ArrayBuffer, auf den über ta.buffer zugegriffen werden kann.Typed Arrays implementieren eine Methode mit dem Schlüssel Symbol.iterator und sind daher iterierbar (siehe Kapitel „Iterables und Iteratoren“ für weitere Informationen). Das bedeutet, dass Sie die for-of-Schleife und ähnliche Mechanismen in ES6 verwenden können.
const ui8 = Uint8Array.of(0,1,2);
for (const byte of ui8) {
console.log(byte);
}
// Output:
// 0
// 1
// 2
ArrayBuffers und DataViews sind nicht iterierbar.
Um ein normales Array in ein Typed Array zu konvertieren, machen Sie es zum Parameter eines Typed Array-Konstruktors. Zum Beispiel:
> const tarr = new Uint8Array([0,1,2]);
Die klassische Methode, ein Typed Array in ein Array zu konvertieren, ist die Ausführung von Array.prototype.slice darauf. Dieser Trick funktioniert für alle Array-ähnlichen Objekte (wie arguments) und Typed Arrays sind Array-ähnlich.
> Array.prototype.slice.call(tarr)
[ 0, 1, 2 ]
In ES6 können Sie den Spread-Operator (...) verwenden, da Typed Arrays iterierbar sind.
> [...tarr]
[ 0, 1, 2 ]
Eine weitere ES6-Alternative ist Array.from(), das mit Iterables oder Array-ähnlichen Objekten funktioniert.
> Array.from(tarr)
[ 0, 1, 2 ]
Einige Methoden erstellen neue Instanzen, die this ähneln. Das Species-Muster ermöglicht es Ihnen zu konfigurieren, welcher Konstruktor dazu verwendet werden soll. Wenn Sie beispielsweise eine Unterklasse MyArray von Array erstellen, ist standardmäßig map() Instanzen von MyArray erstellt. Wenn Sie möchten, dass es Instanzen von Array erstellt, können Sie das Species-Muster verwenden, um dies zu erreichen. Details werden in Abschn. „Das Species-Muster“ im Kapitel über Klassen erläutert.
ArrayBuffers verwenden das Species-Muster an folgenden Stellen:
ArrayBuffer.prototype.slice()Typed Arrays verwenden das Species-Muster an folgenden Stellen:
TypedArray<T>.prototype.filter()TypedArray<T>.prototype.map()TypedArray<T>.prototype.slice()TypedArray<T>.prototype.subarray()DataViews verwenden das Species-Muster nicht.
Wie Sie im Diagramm am Anfang dieses Kapitels sehen konnten, haben alle Typed Array-Klassen (Uint8Array usw.) eine gemeinsame Oberklasse. Ich nenne diese Oberklasse TypedArray, aber sie ist von JavaScript aus nicht direkt zugänglich (die ES6-Spezifikation nennt sie *das intrinsische Objekt %TypedArray%*). TypedArray.prototype enthält alle Methoden von Typed Arrays.
TypedArray Methoden Beide statischen TypedArray-Methoden werden von ihren Unterklassen (Uint8Array usw.) geerbt.
TypedArray.of() Diese Methode hat die Signatur:
TypedArray.of(...items)
Sie erstellt ein neues Typed Array, das eine Instanz von this ist (die Klasse, auf der of() aufgerufen wurde). Die Elemente dieser Instanz sind die Parameter von of().
Sie können of() als eine benutzerdefinierte Literalschreibweise für Typed Arrays betrachten.
> Float32Array.of(0.151, -8, 3.7)
Float32Array [ 0.151, -8, 3.7 ]
TypedArray.from() Diese Methode hat die Signatur:
TypedArray<U>.from(source : Iterable<T>, mapfn? : T => U, thisArg?)
Sie konvertiert das Iterable source in eine Instanz von this (ein Typed Array).
Zum Beispiel sind normale Arrays iterierbar und können mit dieser Methode konvertiert werden:
> Uint16Array.from([0, 1, 2])
Uint16Array [ 0, 1, 2 ]
Typed Arrays sind ebenfalls iterierbar.
> const ui16 = Uint16Array.from(Uint8Array.of(0, 1, 2));
> ui16 instanceof Uint16Array
true
Die optionale mapfn ermöglicht es Ihnen, die Elemente von source zu transformieren, bevor sie zu Elementen des Ergebnisses werden. Warum die beiden Schritte *Mapping* und *Konvertierung* in einem Schritt ausführen? Verglichen mit der separaten Ausführung des ersten Schritts über source.map() gibt es zwei Vorteile:
Um den zweiten Vorteil zu veranschaulichen, verwenden wir map(), um die Elemente eines Typed Arrays zu verdoppeln:
> Int8Array.of(127, 126, 125).map(x => 2 * x)
Int8Array [ -2, -4, -6 ]
Wie Sie sehen, kommt es zu Überläufen und die Werte werden in den Wertebereich von Int8 umgewandelt. Wenn Sie über from() mappen, können Sie den Typ des Ergebnisses so wählen, dass die Werte nicht überlaufen:
> Int16Array.from(Int8Array.of(127, 126, 125), x => 2 * x)
Int16Array [ 254, 252, 250 ]
Laut Allen Wirfs-Brock war das Mappen zwischen Typed Arrays der Grund für den mapfn-Parameter von from().
TypedArray.prototype Eigenschaften Von Typed Array-Methoden akzeptierte Indizes können negativ sein (sie verhalten sich auf diese Weise wie traditionelle Array-Methoden). Offsets müssen nicht-negativ sein. Details finden Sie in Abschn. „Negative Indizes“.
Die folgenden Eigenschaften sind spezifisch für Typed Arrays, normale Arrays haben sie nicht:
get TypedArray<T>.prototype.buffer : ArrayBufferget TypedArray<T>.prototype.byteLength : numberget TypedArray<T>.prototype.byteOffset : numberTypedArray<T>.prototype.set(arrayOrTypedArray, offset=0) : voidarrayOrTypedArray in dieses Typed Array. Das Element am Index 0 von arrayOrTypedArray wird in den Index offset dieses Typed Arrays geschrieben (usw.).arrayOrTypedArray ein normales Array ist, werden seine Elemente in Zahlen konvertiert, die dann in den Elementtyp T dieses Typed Arrays konvertiert werden.arrayOrTypedArray ein Typed Array ist, wird jedes seiner Elemente direkt in den entsprechenden Typ für dieses Typed Array konvertiert. Wenn beide Typed Arrays denselben Elementtyp haben, wird eine schnellere Byte-weise Kopie verwendet.TypedArray<T>.prototype.subarray(begin=0, end=this.length) : TypedArray<T>begin nicht-negativ ist, ist das erste Element des resultierenden Typed Arrays this[begin], das zweite this[begin+1] (usw.). Wenn begin negativ ist, wird es entsprechend konvertiert.Die folgenden Methoden sind im Grunde dieselben wie die Methoden normaler Arrays:
TypedArray<T>.prototype.copyWithin(target : number, start : number, end = this.length) : Thisstart (einschließlich) und end (ausschließlich) liegen, an Indizes, die bei target beginnen. Wenn sich die Bereiche überschneiden und der erstere Bereich zuerst kommt, werden Elemente in umgekehrter Reihenfolge kopiert, um zu vermeiden, dass Quellenelemente überschrieben werden, bevor sie kopiert werden.TypedArray<T>.prototype.entries() : Iterable<[number,T]>TypedArray<T>.prototype.every(callbackfn, thisArg?)true zurück, wenn callbackfn für jedes Element dieses Typed Arrays true zurückgibt. Andernfalls gibt es false zurück. every() stoppt die Verarbeitung beim ersten Mal, wenn callbackfn false zurückgibt.TypedArray<T>.prototype.fill(value, start=0, end=this.length) : voidstart bis end liegen, auf value.TypedArray<T>.prototype.filter(callbackfn, thisArg?) : TypedArray<T>callbackfn true zurückgibt. Im Allgemeinen ist das Ergebnis kürzer als dieses Typed Array.TypedArray<T>.prototype.find(predicate : T => boolean, thisArg?) : Tpredicate true zurückgibt.TypedArray<T>.prototype.findIndex(predicate : T => boolean, thisArg?) : numberpredicate true zurückgibt.TypedArray<T>.prototype.forEach(callbackfn, thisArg?) : voidcallbackfn für jedes Element auf.TypedArray<T>.prototype.indexOf(searchElement, fromIndex=0) : numbersearchElement ist. Die Suche beginnt bei fromIndex.TypedArray<T>.prototype.join(separator : string = ',') : stringseparator.TypedArray<T>.prototype.keys() : Iterable<number>TypedArray<T>.prototype.lastIndexOf(searchElement, fromIndex?) : numbersearchElement ist. Die Suche beginnt bei fromIndex, rückwärts.get TypedArray<T>.prototype.length : numberTypedArray<T>.prototype.map(callbackfn, thisArg?) : TypedArray<T>callbackfn auf das entsprechende Element dieses Typed Arrays ist.TypedArray<T>.prototype.reduce(callbackfn : (previousValue : any, currentElement : T, currentIndex : number, array : TypedArray<T>) => any, initialValue?) : anycallbackfn erhält nacheinander jedes Element zusammen mit dem bisher berechneten Ergebnis und berechnet ein neues Ergebnis. Die Elemente werden von links nach rechts durchlaufen.TypedArray<T>.prototype.reduceRight(callbackfn : (previousValue : any, currentElement : T, currentIndex : number, array : TypedArray<T>) => any, initialValue?) : anycallbackfn erhält nacheinander jedes Element zusammen mit dem bisher berechneten Ergebnis und berechnet ein neues Ergebnis. Die Elemente werden von rechts nach links durchlaufen.TypedArray<T>.prototype.reverse() : Thisthis zurück.TypedArray<T>.prototype.slice(start=0, end=this.length) : TypedArray<T>start (einschließlich) und end (ausschließlich) liegen.TypedArray<T>.prototype.some(callbackfn, thisArg?)true zurück, wenn callbackfn für mindestens ein Element dieses Typed Arrays true zurückgibt. Andernfalls gibt es false zurück. some() stoppt die Verarbeitung beim ersten Mal, wenn callbackfn true zurückgibt.TypedArray<T>.prototype.sort(comparefn? : (number, number) => number)comparefn. Wenn comparefn fehlt, wird aufsteigend sortiert, indem der Kleiner-als-Operator (<) verglichen wird.TypedArray<T>.prototype.toLocaleString(reserved1?, reserved2?)TypedArray<T>.prototype.toString()TypedArray<T>.prototype.values() : Iterable<T>Aufgrund der Tatsache, dass all diese Methoden für Arrays verfügbar sind, können Sie die folgenden beiden Quellen konsultieren, um mehr darüber zu erfahren, wie sie funktionieren:
copyWithin, entries, fill, find, findIndex, keys, values.Beachten Sie, dass normale Array-Methoden zwar generisch sind (jeder Array-ähnliche this ist in Ordnung), die in diesem Abschnitt aufgeführten Methoden jedoch nicht (this muss ein Typed Array sein).
«ElementType»Array Konstruktor Jeder Typed Array-Konstruktor hat einen Namen, der dem Muster «ElementType»Array folgt, wobei «ElementType» einer der Elementtypen in der Tabelle am Anfang ist. Das bedeutet, dass es 9 Konstruktoren für Typed Arrays gibt: Int8Array, Uint8Array, Uint8ClampedArray (Elementtyp Uint8C), Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array.
Jeder Konstruktor hat fünf *überladene* Versionen – er verhält sich unterschiedlich, je nachdem, wie viele Argumente er erhält und welche Typen diese haben:
«ElementType»Array(buffer, byteOffset=0, length?)buffer ist. Es beginnt mit dem Zugriff auf den Puffer am angegebenen byteOffset und hat die angegebene length. Beachten Sie, dass length die Elemente des Typed Arrays zählt (mit jeweils 1–4 Bytes), nicht die Bytes.«ElementType»Array(length)length und dem entsprechenden Puffer (dessen Größe in Bytes length * «ElementType»Array.BYTES_PER_ELEMENT beträgt).«ElementType»Array()length 0. Es erstellt auch einen zugehörigen leeren ArrayBuffer.«ElementType»Array(typedArray)typedArray hat. Zu große oder zu kleine Werte werden entsprechend konvertiert.«ElementType»Array(arrayLikeObject)arrayLikeObject wie ein Array und erstellt ein neues TypedArray mit der gleichen Länge und den gleichen Elementen. Zu große oder zu kleine Werte werden entsprechend konvertiert.Der folgende Code zeigt drei verschiedene Möglichkeiten, dasselbe Typed Array zu erstellen:
const tarr1 = new Uint8Array([1,2,3]);
const tarr2 = Uint8Array.of(1,2,3);
const tarr3 = new Uint8Array(3);
tarr3[0] = 0;
tarr3[1] = 1;
tarr3[2] = 2;
«ElementType»Array Eigenschaften «ElementType»Array.BYTES_PER_ELEMENT > Uint8Array.BYTES_PER_ELEMENT
1
> Int16Array.BYTES_PER_ELEMENT
2
> Float64Array.BYTES_PER_ELEMENT
8
«ElementType»Array.prototype Eigenschaften «ElementType»Array.prototype.BYTES_PER_ELEMENT«ElementType»Array.BYTES_PER_ELEMENT.Typed Arrays haben keine concat()-Methode wie normale Arrays. Der Workaround besteht darin, die Methode zu verwenden
typedArray.set(arrayOrTypedArray, offset=0)
Diese Methode kopiert ein vorhandenes Typed Array (oder normales Array) in typedArray am Index offset. Dann müssen Sie nur sicherstellen, dass typedArray groß genug ist, um alle (Typed) Arrays aufzunehmen, die Sie konkatenieren möchten.
function concatenate(resultConstructor, ...arrays) {
let totalLength = 0;
for (const arr of arrays) {
totalLength += arr.length;
}
const result = new resultConstructor(totalLength);
let offset = 0;
for (const arr of arrays) {
result.set(arr, offset);
offset += arr.length;
}
return result;
}
console.log(concatenate(Uint8Array,
Uint8Array.of(1, 2), Uint8Array.of(3, 4)));
// Uint8Array [1, 2, 3, 4]
DataView Konstruktor DataView(buffer, byteOffset=0, byteLength=buffer.byteLength-byteOffset)buffer gespeichert sind. Standardmäßig kann die neue DataView auf den gesamten buffer zugreifen. Die letzten beiden Parameter ermöglichen es Ihnen, dies zu ändern.DataView.prototype Eigenschaften get DataView.prototype.bufferget DataView.prototype.byteLengthget DataView.prototype.byteOffsetDataView.prototype.get«ElementType»(byteOffset, littleEndian=false)«ElementType» kann sein: Float32, Float64, Int8, Int16, Int32, Uint8, Uint16, Uint32DataView.prototype.set«ElementType»(byteOffset, value, littleEndian=false)value in den Puffer dieser DataView.«ElementType» kann sein: Float32, Float64, Int8, Int16, Int32, Uint8, Uint16, Uint32Typed Arrays gibt es schon seit einiger Zeit, daher gibt es eine ganze Reihe von Browser-APIs, die sie unterstützen.
Die File API ermöglicht den Zugriff auf lokale Dateien. Der folgende Code zeigt, wie die Bytes einer übermittelten lokalen Datei in einem ArrayBuffer abgerufen werden können.
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function () {
const arrayBuffer = reader.result;
···
};
XMLHttpRequest In neueren Versionen der XMLHttpRequest API können Sie die Ergebnisse in einem ArrayBuffer liefern lassen.
const xhr = new XMLHttpRequest();
xhr.open('GET', someUrl);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
const arrayBuffer = xhr.response;
···
};
xhr.send();
Ähnlich wie XMLHttpRequest ermöglicht die Fetch API das Anfordern von Ressourcen. Sie basiert jedoch auf Promises, was die Verwendung erleichtert. Der folgende Code zeigt, wie der Inhalt, auf den url verweist, als ArrayBuffer heruntergeladen wird.
fetch(url)
.then(request => request.arrayBuffer())
.then(arrayBuffer => ···);
Zitat der HTML5-Spezifikation::
Das
canvas-Element stellt Skripten eine auflösungsabhängige Bitmap-Leinwand zur Verfügung, die zum Rendern von Grafiken, Spielgrafiken, Kunst oder anderen visuellen Bildern im Handumdrehen verwendet werden kann.
Der 2D-Kontext von canvas ermöglicht es Ihnen, die Bitmap-Daten als Instanz von Uint8ClampedArray abzurufen.
const canvas = document.getElementById('my_canvas');
const context = canvas.getContext('2d');
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
const uint8ClampedArray = imageData.data;
WebSockets ermöglichen das Senden und Empfangen von Binärdaten über ArrayBuffers.
const socket = new WebSocket('ws://127.0.0.1:8081');
socket.binaryType = 'arraybuffer';
// Wait until socket is open
socket.addEventListener('open', function (event) {
// Send binary data
const typedArray = new Uint8Array(4);
socket.send(typedArray.buffer);
});
// Receive binary data
socket.addEventListener('message', function (event) {
const arrayBuffer = event.data;
···
});
<audio> und <video>. Die Media Source Extensions API ermöglicht Ihnen die Erstellung von Streams, die über diese Elemente abgespielt werden können. Sie können solche Streams mit Binärdaten über ArrayBuffers, Typed Arrays oder DataViews ergänzen.postMessage() an einen Worker senden, können entweder die Nachricht (die geklont wird) oder die übertragbaren Objekte ArrayBuffers enthalten.postMessage().Das Beispiel ist eine Webseite, auf der Sie eine JPEG-Datei hochladen und deren Struktur parsen können, um die Höhe und Breite des Bildes und mehr zu ermitteln.
Eine JPEG-Datei ist eine Abfolge von *Segmenten* (typisierte Daten). Jedes Segment beginnt mit den folgenden vier Bytes:
JPEG-Dateien sind auf allen Plattformen Big-Endian. Daher zeigt dieses Beispiel, wie wichtig es ist, dass wir beim Verwenden von DataViews die Endianness angeben können.
Die folgende Funktion processArrayBuffer() ist eine gekürzte Version des tatsächlichen Codes; ich habe ein paar Fehlerprüfungen entfernt, um die Übersichtlichkeit zu verbessern. processArrayBuffer() empfängt einen ArrayBuffer mit dem Inhalt der übermittelten JPEG-Datei und iteriert über seine Segmente.
// JPEG is big endian
var IS_LITTLE_ENDIAN = false;
function processArrayBuffer(arrayBuffer) {
try {
var dv = new DataView(arrayBuffer);
···
var ptr = 2;
while (true) {
···
var lastPtr = ptr;
enforceValue(0xFF, dv.getUint8(ptr),
'Not a marker');
ptr++;
var marker = dv.getUint8(ptr);
ptr++;
var len = dv.getUint16(ptr, IS_LITTLE_ENDIAN);
ptr += len;
logInfo('Marker: '+hex(marker)+' ('+len+' byte(s))');
···
// Did we find what we were looking for?
if (marker === 0xC0) { // SOF0
logInfo(decodeSOF0(dv, lastPtr));
break;
}
}
} catch (e) {
logError(e.message);
}
}
Dieser Code verwendet die folgenden Hilfsfunktionen (die hier nicht gezeigt werden)
enforceValue() löst einen Fehler aus, wenn der erwartete Wert (erster Parameter) nicht mit dem tatsächlichen Wert (zweiter Parameter) übereinstimmt.logInfo() und logError() zeigen Meldungen auf der Seite an.hex() wandelt eine Zahl in eine Zeichenkette mit zwei Hexadezimalziffern um.decodeSOF0() parst das Segment SOF0
function decodeSOF0(dv, start) {
// Example (16x16):
// FF C0 00 11 08 00 10 00 10 03 01 22 00 02 11 01 03 11 01
var data = {};
start += 4; // skip marker 0xFFC0 and segment length 0x0011
var data = {
bitsPerColorComponent: dv.getUint8(start), // usually 0x08
imageHeight: dv.getUint16(start+1, IS_LITTLE_ENDIAN),
imageWidth: dv.getUint16(start+3, IS_LITTLE_ENDIAN),
numberOfColorComponents: dv.getUint8(start+5),
};
return JSON.stringify(data, null, 4);
}
Weitere Informationen zur Struktur von JPEG-Dateien
Ein Großteil der Typed Array API wird von allen modernen JavaScript-Engines implementiert, aber mehrere Funktionen sind neu in ECMAScript 6
TypedArray<T>.from(), TypedArray<T>.of()TypedArray<T>.prototype.map() etc.TypedArray<T> die Oberklasse aller Typed Array-Klassen istEs kann eine Weile dauern, bis diese überall verfügbar sind. Wie üblich beschreibt kangax' „ES6-Kompatibilitätstabelle“ den Status quo.