web-dev-qa-db-ger.com

Was ist der JavaScript >>> Operator und wie benutzt man ihn?

Ich habe mir Code von Mozilla angesehen, der Array eine Filtermethode hinzufügt, und eine Codezeile, die mich verwirrte.

var len = this.length >>> 0;

Ich habe noch nie zuvor gesehen, dass >>> in JavaScript verwendet wird.
Was ist das und was macht es?

138
Kenneth J

Nicht-Zahlen werden nicht nur in Zahlen konvertiert, sondern auch in Zahlen, die als vorzeichenlose 32-Bit-Ints ausgedrückt werden können.

Obwohl die Zahlen in JavaScript Gleitkommazahlen (*) mit doppelter Genauigkeit sind, sind die bitweisen Operatoren (<<, >>, &, | Und ~ ) werden als Operationen für 32-Bit-Ganzzahlen definiert. Bei einer bitweisen Operation wird die Zahl in ein 32-Bit-Int mit Vorzeichen konvertiert, wobei Brüche und höherwertige Bits als 32 verloren gehen, bevor die Berechnung ausgeführt und anschließend wieder in Zahl konvertiert wird.

Eine bitweise Operation ohne tatsächliche Auswirkung, wie eine Verschiebung von 0 Bits nach rechts >>0, Ist also ein schneller Weg, um eine Zahl zu runden und sicherzustellen, dass sie im 32-Bit-Int-Bereich liegt. Darüber hinaus konvertiert der dreifache Operator >>> Nach dem Ausführen seiner Operation ohne Vorzeichen die Ergebnisse seiner Berechnung in Zahl als Ganzzahl ohne Vorzeichen und nicht als Ganzzahl mit Vorzeichen, wie es die anderen tun, sodass Negative in die Zahl 32 konvertiert werden können -bit-two's-complement Version als große Zahl. Mit >>>0 Stellen Sie sicher, dass Sie eine Ganzzahl zwischen 0 und 0xFFFFFFFF haben.

In diesem Fall ist dies nützlich, da ECMAScript Array-Indizes in Form von vorzeichenlosen 32-Bit-Ints definiert. Wenn Sie also versuchen, array.filter So zu implementieren, dass es genau dem entspricht, was der ECMAScript Fifth Edition-Standard angibt, würden Sie die Zahl in ein 32-Bit-Int ohne Vorzeichen wie dieses umwandeln.

(In Wirklichkeit gibt es wenig praktischen Grund dafür, da die Leute hoffentlich nicht array.length Auf 0.5, -1, 1e21 Oder 'LEMONS'. Es handelt sich jedoch um JavaScript-Autoren, von denen wir sprechen.

Zusammenfassung:

1>>>0            === 1
-1>>>0           === 0xFFFFFFFF          -1>>0    === -1
1.7>>>0          === 1
0x100000002>>>0  === 2
1e21>>>0         === 0xDEA00000          1e21>>0  === -0x21600000
Infinity>>>0     === 0
NaN>>>0          === 0
null>>>0         === 0
'1'>>>0          === 1
'x'>>>0          === 0
Object>>>0       === 0

(*: Nun, sie verhalten sich wie Floats. Es würde mich nicht überraschen, wenn aus Performancegründen einige JavaScript-Engines tatsächlich Ints verwenden würden, wenn dies möglich wäre. Dies wäre jedoch ein Implementierungsdetail, das Sie nicht benötigen würden Vorteil von.)

192
bobince

Der vorzeichenlose Rechts-Shift-Operator wird in allen Implementierungen der Methode Array-Extras von Mozilla verwendet, um sicherzustellen, dass die Eigenschaft length eine vorzeichenlose 32-Bit-Ganzzahl ist .

Die length -Eigenschaft von Array-Objekten ist beschrieben in der Spezifikation als:

Jedes Array-Objekt verfügt über eine length-Eigenschaft, deren Wert immer eine nicht negative Ganzzahl kleiner als 2 ist32.

Dieser Operator ist der kürzeste Weg, um dies zu erreichen. Interne Array-Methoden verwenden die Operation ToUint32 , aber diese Methode ist für Implementierungszwecke nicht zugänglich und in der Spezifikation vorhanden.

Die Mozilla Array-Extras -Implementierungen versuchen ECMAScript 5 kompatibel zu sein, siehe Beschreibung der Array.prototype.indexOf -Methode (§ 15.4.4.14):

 1. Sei O das Ergebnis des Aufrufs von ToObject, wobei dieser Wert 
 Als Argument übergeben wird. 
 2. Sei lenValue das Ergebnis des Aufrufs der internen Methode [[Get]] von O mit 
 Dem Argument "length". 
 3. Sei len  ToUint32 (lenValue) . 
 .... 

Wie Sie sehen, möchten sie nur das Verhalten der ToUint32 - Methode reproduzieren, um die ES5-Spezifikation für eine ES3-Implementierung zu erfüllen, und wie ich bereits sagte, den vorzeichenlosen rechten Shift-Operator ist der einfachste Weg.

56
CMS

Dies ist der Operator vorzeichenlose Verschiebung des rechten Bits . Der Unterschied zwischen diesem und dem vorzeichenbehafteten Rechtsbitverschiebungsoperator besteht darin, dass der vorzeichenlose Rechtsbitverschiebungsoperator ( >>> ) wird mit Nullen von links und dem vorzeichenbehafteten Rechtsbitverschiebungsoperator gefüllt ( >> ) wird mit dem Vorzeichenbit gefüllt, wodurch das Vorzeichen des numerischen Werts beim Verschieben beibehalten wird.

30
driis

Driis hat ausreichend erklärt, was der Bediener ist und was er tut. Hier ist die Bedeutung dahinter/warum es verwendet wurde:

Wenn Sie eine beliebige Richtung um 0 Verschieben, wird die ursprüngliche Zahl zurückgegeben und null in 0 Umgewandelt. Es scheint, dass der Beispielcode, den Sie betrachten, this.length >>> 0 Verwendet, um sicherzustellen, dass len numerisch ist, auch wenn this.length Nicht definiert ist.

Für viele Menschen sind bitweise Operationen unklar (und Douglas Crockford/jslint rät davon ab, solche Dinge zu verwenden). Das bedeutet nicht, dass es falsch ist, aber es gibt günstigere und bekanntere Methoden, um den Code besser lesbar zu machen. Eine klarere Methode, um sicherzustellen, dass len0 Ist, ist eine der beiden folgenden Methoden.

// Cast this.length to a number
var len = +this.length;

oder

// Cast this.length to a number, or use 0 if this.length is
// NaN/undefined (evaluates to false)
var len = +this.length || 0; 
28
Justin Johnson

>>> Ist der vorzeichenlose rechte Shift-Operator ( siehe S. 76 der JavaScript 1.5-Spezifikation ), im Gegensatz zum >>, dem vorzeichenbehafteten rechten Schalthebel.

>>> Ändert die Ergebnisse des Verschiebens negativer Zahlen, da es das Vorzeichenbit beim Verschieben nicht beibehält. Die Konsequenzen daraus können beispielsweise von einem Dolmetscher verstanden werden:

$ 1 >> 0
1
$ 0 >> 0
0
$ -1 >> 0
-1
$ 1 >>> 0
1
$ 0 >>> 0
0
$ -1 >>> 0
4294967295
$(-1 >>> 0).toString(16)
"ffffffff"
$ "cabbage" >>> 0
0

Was hier wahrscheinlich getan werden soll, ist, die Länge oder 0 zu erhalten, wenn die Länge undefiniert ist oder keine ganze Zahl, wie im obigen Beispiel "cabbage". Ich denke in diesem Fall ist es sicher anzunehmen, dass this.length Niemals < 0 Sein wird. Trotzdem würde ich argumentieren, dass dieses Beispiel aus zwei Gründen ein böser Hack ist:

  1. Das Verhalten von <<< Bei Verwendung negativer Zahlen ist im obigen Beispiel wahrscheinlich nicht beabsichtigt (oder wahrscheinlich).

  2. Die Absicht des Codes ist nicht offensichtlich , wie die Existenz dieser Frage belegt.

Die beste Vorgehensweise ist wahrscheinlich, etwas besser lesbares zu verwenden, es sei denn, die Leistung ist absolut kritisch:

isNaN(parseInt(foo)) ? 0 : parseInt(foo)
15
fmark

Zwei Gründe:

  1. Das Ergebnis von >>> ist ein "Integral"

  2. undefined >>> 0 = 0 (da JS versucht, die LFS in einen numerischen Kontext zu zwingen, funktioniert dies auch für "foo" >>> 0 usw.)

Denken Sie daran, dass Zahlen in JS eine interne Darstellung von double haben. Es ist nur ein "schneller" Weg, um die Länge der Eingabe zu überprüfen.

Allerdings , -1 >>> 0 (oops, wahrscheinlich keine gewünschte Länge!)

10
user166390

Beispiel Java Code unten erklärt gut:

int x = 64;

System.out.println("x >>> 3 = "  + (x >>> 3));
System.out.println("x >> 3 = "  + (x >> 3));
System.out.println(Integer.toBinaryString(x >>> 3));
System.out.println(Integer.toBinaryString(x >> 3));

Ausgabe ist die folgende:

x >>> 3 = 536870904
x >> 3 = -8
11111111111111111111111111000
11111111111111111111111111111000
0
nitinsridar