Signatur
Beschreibung
Der Zuweisungsoperator >>>= ist die Kurzform von x = x >>> y. Der Unterschied: Der Ausdruck x wird nur einmal ausgewertet. Das ist wichtig, wenn links zum Beispiel obj[getKey()] steht. Der linke Operand wird in eine vorzeichenlose 32-Bit-Ganzzahl (Uint32) umgewandelt. Dann werden seine Bits um y Stellen nach rechts geschoben, und von links werden immer Nullen nachgefüllt.
Anders als beim vorzeichenbehafteten Rechtsshift >>= bleibt das Vorzeichenbit hier nicht erhalten. Deshalb ist das Ergebnis immer eine Zahl zwischen 0 und 4294967295 (232−1). Negative Zahlen werden also zu großen positiven Werten. Ein oft genutzter Trick ist x >>>= 0: Damit wandelt man einen Wert in eine vorzeichenlose 32-Bit-Zahl um. Das braucht man häufig bei Hash-Funktionen, Prüfsummen (CRC32) oder Farbwerten.
Typische Einsatzgebiete:
- Bits einzeln abarbeiten, zum Beispiel gesetzte Bits zählen oder ein Bitfeld durchlaufen
- Bytes aus einem 32-Bit-Wert herauslösen (RGBA-Farben, Netzwerkprotokolle, Binärformate)
- Zwischenergebnisse von Hash- oder Zufallszahlen-Algorithmen in den vorzeichenlosen Wertebereich bringen
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $x Pflicht | Variable | Eigenschaft (number) | Ziel der Zuweisung. Das muss eine zuweisbare Referenz sein, also eine let/var-Variable, eine Objekteigenschaft oder ein Array-Element. Der Wert wird mit ToUint32 in eine vorzeichenlose 32-Bit-Ganzzahl umgewandelt. |
|
| $y Pflicht | number | Anzahl der Bitstellen, um die verschoben wird. Es zählen nur die unteren 5 Bits (y & 31), also Werte von 0 bis 31. 32 wirkt deshalb wie 0. |
Rückgabewert
x, eine Ganzzahl zwischen 0 und 4294967295. Der gesamte Zuweisungsausdruck liefert ebenfalls diesen Wert.Beispiele
Grundlagen: positive und negative Werte
let a = 5; // 0b101
a >>>= 2;
console.log(a); // 0b1
let b = -5; // als Uint32: 4294967291
b >>>= 2;
console.log(b);
// Vergleich mit dem vorzeichenbehafteten Shift
let c = -5;
c >>= 2;
console.log(c);
Gesetzte Bits zählen (funktioniert auch bei negativen Zahlen)
const popcount = (n) => {
let count = 0;
while (n) {
count += n & 1;
n >>>= 1; // mit >>= würde die Schleife bei negativen Zahlen nie enden
}
return count;
};
console.log(popcount(0b1011)); // 3
console.log(popcount(-1)); // alle 32 Bits gesetzt
RGBA-Farbwert in einzelne Bytes zerlegen
let color = 0xFF8800CC; // R=255, G=136, B=0, A=204
const bytes = [];
for (let i = 0; i < 4; i++) {
bytes.unshift(color & 0xFF);
color >>>= 8;
}
console.log(bytes);
FNV-1a-Hash als vorzeichenlose Zahl
const fnv1a = (str) => {
let hash = 0x811c9dc5;
for (const ch of str) {
hash ^= ch.codePointAt(0);
hash = Math.imul(hash, 0x01000193);
}
hash >>>= 0; // in den Bereich 0 … 2^32−1 bringen
return hash.toString(16).padStart(8, '0');
};
console.log(fnv1a('hello'));
Fallstricke: Shift-Anzahl, BigInt und const
let x = 256;
x >>>= 32; // 32 & 31 === 0, also keine Verschiebung
console.log(x);
x >>>= 33; // entspricht >>>= 1
console.log(x);
let big = 16n;
try {
big >>>= 1n;
} catch (e) {
console.log(e.constructor.name);
}
const k = 8;
try {
k >>>= 1;
} catch (e) {
console.log(e.constructor.name);
}
// Wichtig · Fallstricke
- Kein BigInt: Für
BigIntgibt es keinen vorzeichenlosen Rechtsshift, weil BigInts keine feste Bitbreite haben.>>>=mit BigInt-Operanden wirft einenTypeError. Nimm stattdessen>>=oderBigInt.asUintN(). - Shift-Anzahl wird maskiert: Es zählt nur
y & 31. Deshalb setztx >>>= 32den Wert nicht auf 0. - 32-Bit-Kürzung: Nachkommastellen und Bits oberhalb von Bit 31 gehen verloren.
2**32 + 5wird zu5,3.9wird zu3.NaN,Infinityund nicht-numerische Strings ergeben0. - Negative Werte: Schon
>>>= 0macht aus-1den Wert4294967295. Das ist bei vorzeichenbehafteten Daten oft unerwünscht. - Mit
const-Bindungen gibt es einenTypeError, weil eine Zuweisung stattfindet. Für die Arbeit mit großen Binärdaten sind oftUint32ArrayoderDataViewbesser geeignet.