Start · Sprachen · JavaScript · Referenz · TypedArray.prototype.copyWithin()

TypedArray.prototype.copyWithin()

Methode

Kopiert einen Abschnitt eines Typ-Arrays an eine andere Position im selben Typ-Array und gibt es verändert zurück, ohne die Länge zu ändern.

seit JavaScript ES2015 Kategorie: method-property

Signatur

TypedArray.prototype.copyWithin(target, start, end)

Beschreibung

copyWithin() verschiebt bzw. dupliziert einen Bereich von Elementen innerhalb desselben Typ-Arrays (z. B. Uint8Array, Float32Array). Die Elemente von start bis ausschließlich end werden ab Index target hineingeschrieben. Das Array wird direkt verändert (mutiert) und die Länge bleibt immer gleich: Was über das Ende hinausreichen würde, wird abgeschnitten.

Die Methode verhält sich wie Array.prototype.copyWithin(), arbeitet aber auf dem zugrunde liegenden Speicher (ArrayBuffer) und ist dadurch sehr schnell – intern entspricht sie einem memmove. Sie eignet sich ideal für Ringpuffer, das Verschieben von Audio- oder Bilddaten, Scroll-Effekte in Pixelpuffern oder das Entfernen/Einfügen von Blöcken in Binärdaten ohne neue Allokation.

Alle Indizes dürfen negativ sein und werden dann vom Ende aus gezählt (-1 = letztes Element). Überlappende Quell- und Zielbereiche werden korrekt behandelt: Es wird so kopiert, als ob die Quelldaten vorher zwischengespeichert worden wären.

Parameter

Name Typ Default Beschreibung
$target Pflicht number Nullbasierter Zielindex, ab dem die Elemente geschrieben werden. Negative Werte zählen vom Ende. Ist target ≥ Länge, wird nichts kopiert.
$start number 0 Nullbasierter Index, ab dem kopiert wird. Negative Werte zählen vom Ende.
$end number this.length Index, vor dem das Kopieren endet (exklusiv). Negative Werte zählen vom Ende.

Rückgabewert

Typ
TypedArray
Beschreibung
Dasselbe, nun veränderte Typ-Array (keine Kopie). Ermöglicht Methodenverkettung.

Beispiele

Grundlegende Verwendung

const arr = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);

// Elemente ab Index 3 an den Anfang kopieren
arr.copyWithin(0, 3);
console.log(arr);

const b = new Uint8Array([1, 2, 3, 4, 5]);
// Index 0–1 nach Index 3 kopieren
b.copyWithin(3, 0, 2);
console.log(b);
Uint8Array(8) [4, 5, 6, 7, 8, 6, 7, 8] Uint8Array(5) [1, 2, 3, 1, 2]

Negative Indizes

const data = new Int16Array([10, 20, 30, 40, 50]);

// Die letzten zwei Elemente an den Anfang kopieren
data.copyWithin(0, -2);
console.log(data);
Int16Array(5) [40, 50, 30, 40, 50]

Gleitendes Fenster für Audio-Samples (Puffer nach links schieben)

const WINDOW = 8;
const buffer = new Float32Array(WINDOW);

const pushSamples = (samples) => {
  const n = samples.length;
  // Alte Daten um n nach links schieben, ohne neuen Speicher anzulegen
  buffer.copyWithin(0, n);
  // Neue Samples ans Ende schreiben
  buffer.set(samples, WINDOW - n);
};

pushSamples(new Float32Array([0.1, 0.2, 0.3]));
pushSamples(new Float32Array([0.4, 0.5]));
console.log(Array.from(buffer, (v) => v.toFixed(1)).join(', '));
0.0, 0.0, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5

Pixelzeilen in einem RGBA-Puffer nach oben scrollen

const width = 4, height = 3, bpp = 4; // RGBA
const rowBytes = width * bpp;
const pixels = new Uint8ClampedArray(width * height * bpp);

// Jede Zeile mit ihrer Zeilennummer füllen
for (let y = 0; y < height; y++) {
  pixels.fill(y + 1, y * rowBytes, (y + 1) * rowBytes);
}

// Um eine Zeile nach oben scrollen, letzte Zeile leeren
pixels.copyWithin(0, rowBytes).fill(0, (height - 1) * rowBytes);

console.log(pixels[0], pixels[rowBytes], pixels[2 * rowBytes]);
2 3 0

// Wichtig · Fallstricke

  • Mutiert das Original: Anders als slice() oder toSorted() wird kein neues Array erzeugt. Wer die Ursprungsdaten braucht, muss vorher kopieren (z. B. arr.slice()).
  • Geteilter Speicher: Alle Ansichten (subarray(), andere Typ-Arrays, DataView) auf denselben ArrayBuffer sehen die Änderung sofort.
  • Keine Typumwandlung: Es werden rohe Bytes des Elementtyps kopiert – Werte bleiben exakt erhalten, es gibt kein Clamping oder Runden.
  • Nicht-ganzzahlige Indizes werden abgeschnitten (1.7 → 1), NaN/undefined gelten als 0 (bzw. bei end als Länge).
  • Ist der ArrayBuffer detached (z. B. nach postMessage mit Transfer), wird ein TypeError geworfen. Bei größenveränderlichen Puffern (resizable) wird die Kopie auf die aktuelle Länge begrenzt.
  • Die Methode ist nicht generisch: Aufruf auf normalen Arrays oder Objekten via call() wirft einen TypeError – dafür gibt es Array.prototype.copyWithin().
  • Kompatibilität: In allen modernen Browsern und Node.js (ab 4) verfügbar; nicht im Internet Explorer.