Start · Sprachen · JavaScript · Referenz · ArrayBuffer[Symbol.species]

ArrayBuffer[Symbol.species]

Eigenschaft

Statischer Getter, der den Konstruktor liefert, mit dem <code>ArrayBuffer</code>-Methoden wie <code>slice()</code> neue Buffer-Objekte erzeugen. Standardmäßig ist das <code>this</code>.

seit JavaScript ES2015 Kategorie: method-property

Signatur

get ArrayBuffer[Symbol.species]

Beschreibung

ArrayBuffer[Symbol.species] ist eine statische Zugriffseigenschaft, also ein Getter ohne Setter. Sie legt fest, welcher Konstruktor benutzt wird, wenn eine ArrayBuffer-Methode aus einem vorhandenen Buffer einen neuen Buffer erzeugt. Die Standard-Umsetzung gibt einfach this zurück. Beim Aufruf auf ArrayBuffer ist das also ArrayBuffer selbst, bei einer Unterklasse die Unterklasse.

Praktisch betrifft das vor allem ArrayBuffer.prototype.slice(). Die Methode liest this.constructor[Symbol.species] aus und erzeugt damit den Ergebnis-Buffer. Leitet man von ArrayBuffer ab, liefert slice() deshalb automatisch wieder eine Instanz der Unterklasse. Die neueren Methoden transfer() und transferToFixedLength() beachten Symbol.species nicht. Sie erzeugen immer ein normales ArrayBuffer.

Man überschreibt die Eigenschaft in einer Unterklasse mit static get [Symbol.species](). Das lohnt sich, wenn abgeleitete Ergebnisse wieder schlichte ArrayBuffer-Objekte sein sollen, etwa weil der Konstruktor der Unterklasse zusätzliche Argumente erwartet oder Nebenwirkungen hat.

Rückgabewert

Typ
Function
Beschreibung
Der Wert von this, also der Konstruktor, auf dem der Getter aufgerufen wurde. Mit ihm werden neue Buffer in slice() erzeugt.

Beispiele

Standardwert abfragen

// Standardmäßig liefert der Getter einfach den Konstruktor selbst zurück
console.log(ArrayBuffer[Symbol.species] === ArrayBuffer);

// Auch über eine Instanz erreichbar
const buf = new ArrayBuffer(16);
console.log(buf.constructor[Symbol.species] === ArrayBuffer);
true true

Unterklasse: slice() liefert die Unterklasse

class ChunkBuffer extends ArrayBuffer {
  describe() {
    return `ChunkBuffer mit ${this.byteLength} Bytes`;
  }
}

const chunk = new ChunkBuffer(8);
const part = chunk.slice(0, 4);

console.log(ChunkBuffer[Symbol.species] === ChunkBuffer);
console.log(part instanceof ChunkBuffer);
console.log(part.describe());
true true ChunkBuffer mit 4 Bytes

Species überschreiben: slice() liefert ein normales ArrayBuffer

class LoggedBuffer extends ArrayBuffer {
  constructor(length) {
    super(length);
    console.log(`LoggedBuffer angelegt: ${length} Bytes`);
  }

  // Abgeleitete Buffer sollen normale ArrayBuffer sein, also ohne Logging
  static get [Symbol.species]() {
    return ArrayBuffer;
  }
}

const logged = new LoggedBuffer(32);
const copy = logged.slice(0, 16);

console.log(copy instanceof LoggedBuffer);
console.log(copy.constructor === ArrayBuffer);
LoggedBuffer angelegt: 32 Bytes false true

transfer() beachtet Species nicht

class MyBuffer extends ArrayBuffer {}

const original = new MyBuffer(8);
const moved = original.transfer();

console.log(moved instanceof MyBuffer);
console.log(original.detached);
false true

// Wichtig · Fallstricke

  • Prüfungen in slice(): Das Objekt, das der Species-Konstruktor erzeugt, muss ein echtes, nicht geteiltes ArrayBuffer sein. Es darf nicht das Ausgangsobjekt selbst sein, darf nicht abgekoppelt (detached) sein und muss mindestens so viele Bytes haben wie angefordert. Sonst wirft slice() einen TypeError.
  • Nur Getter: Es gibt keinen Setter. Eine Zuweisung wie ArrayBuffer[Symbol.species] = X ändert nichts und wirft im Strict Mode einen Fehler. Zum Überschreiben nimmt man static get [Symbol.species]() in einer Unterklasse oder Object.defineProperty().
  • Ausnahmen: transfer() und transferToFixedLength() (ES2024) sowie resize() werten Symbol.species nicht aus.
  • Sicherheit und Performance: Mit Symbol.species kann Fremdcode festlegen, welcher Konstruktor aufgerufen wird. Das war in der Vergangenheit eine Quelle von Engine-Sicherheitslücken und verlangsamt Optimierungen. In sicherheitskritischem Code sollte man nicht darauf bauen und stattdessen Buffer ausdrücklich mit new ArrayBuffer() erzeugen.
  • SharedArrayBuffer hat einen eigenen SharedArrayBuffer[Symbol.species] mit gleichem Verhalten.
  • Unterstützt von allen modernen Browsern und von Node.js ab Version 6.5.