Ich habe mir Code von Mozilla angesehen, der Array eine Filtermethode hinzufügt, und er hatte eine Codezeile, die mich verwirrte.
var len = this.length >>> 0;
Ich habe noch nie >>> in JavaScript verwendet gesehen.
Was ist das und was macht es?
javascript
operators
bit-shift
Kenneth J.
quelle
quelle
Array.prototype.push
/Array.prototype.pop
- hexmen.com/blog/2006/12/push-and-pop (obwohl er die Tests durchgeführt hat, haha).Antworten:
Nicht-Zahlen werden nicht nur in Zahlen konvertiert, sondern auch in Zahlen, die als vorzeichenlose 32-Bit-Ints ausgedrückt werden können.
Obwohl JavaScript die Zahlen mit doppelter Genauigkeit Schwimmer (*) sind die Bit - Operatoren (
<<
,>>
,&
,|
und~
) auf 32-Bit - Integer in Bezug auf die Operationen definiert. Durch eine bitweise 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 durchgeführt und dann wieder in Zahl konvertiert wird.Eine bitweise Operation ohne tatsächlichen Effekt, wie eine Verschiebung von 0 Bits nach rechts
>>0
, ist also eine schnelle Möglichkeit, eine Zahl zu runden und sicherzustellen, dass sie im 32-Bit-Int-Bereich liegt. Darüber hinaus>>>
konvertiert der Dreifachoperator nach seiner vorzeichenlosen Operation die Ergebnisse seiner Berechnung als vorzeichenlose Ganzzahl in die vorzeichenbehaftete Ganzzahl und nicht in die vorzeichenbehaftete Ganzzahl, sodass die Negative in das 32-Bit-Zwei-Komplement konvertiert werden können Version als große Zahl. Durch>>>0
die Verwendung wird sichergestellt, dass Sie eine Ganzzahl zwischen 0 und 0xFFFFFFFF haben.In diesem Fall ist dies nützlich, da ECMAScript Array-Indizes in Form von 32-Bit-Ints ohne Vorzeichen definiert. Wenn Sie also versuchen,
array.filter
auf eine Weise zu implementieren , die genau das dupliziert, was der ECMAScript Fifth Edition-Standard sagt, würden Sie die Zahl wie folgt in 32-Bit-Int ohne Vorzeichen umwandeln.(In Wirklichkeit gibt es wenig praktische Notwendigkeit dafür , wie hoffentlich die Menschen gehen nicht einstellen werden ,
array.length
um0.5
,-1
,1e21
oder'LEMONS'
. Aber das ist JavaScript Autoren wir reden, so dass Sie nie wissen ...)Zusammenfassung:
(*: Nun, sie verhalten sich wie Floats. Es würde mich nicht wundern, wenn eine JavaScript-Engine aus Leistungsgründen tatsächlich Ints verwenden würde, wenn dies möglich wäre. Aber das wäre ein Implementierungsdetail, das Sie nicht benötigen würden Vorteil von.)
quelle
RangeError: invalid array length
.Array.prototype.filter.call
), sodass diesarray
möglicherweise nicht real istArray
: Es kann sich um eine andere benutzerdefinierte Klasse handeln. (Leider kann es nicht zuverlässig eine NodeList sein, wenn Sie das wirklich wollen, da dies ein Host-Objekt ist. Damit bleibt der einzige Ort, an dem Sie dies realistisch alsarguments
Pseudo-Array tun würden .)if
Aussage dafür aussehen, wenn versucht wird festzustellen, dass die linke Seite der Bewertung kein Int ist?'lemons'>>>0 === 0 && 0 >>>0 === 0
bewertet als wahr? obwohl Zitronen offensichtlich ein Wort ist ..?Der vorzeichenlose Rechtsverschiebungsoperator wird in allen Methodenimplementierungen des Array-Extra von Mozilla verwendet, um sicherzustellen, dass die
length
Eigenschaft eine vorzeichenlose 32-Bit-Ganzzahl ist .Die
length
Eigenschaft von Array-Objekten wird in der Spezifikation wie folgt beschrieben :Dieser Operator ist der kürzeste Weg, um dies zu erreichen. Interne Array-Methoden verwenden die
ToUint32
Operation, aber diese Methode ist nicht verfügbar und existiert in der Spezifikation für Implementierungszwecke.Die Mozilla- Array-Extras- Implementierungen versuchen, ECMAScript 5- kompatibel zu sein.
Array.prototype.indexOf
Beachten Sie die Beschreibung der Methode (§ 15.4.4.14):Wie Sie sehen können, möchten sie nur das Verhalten der
ToUint32
Methode reproduzieren , um der ES5-Spezifikation für eine ES3-Implementierung zu entsprechen, und wie ich bereits sagte, ist der vorzeichenlose Rechtsschichtoperator der einfachste Weg.quelle
ToUint32
scheint mir diese Art von etwas unnötig.Array.prototype
Methoden absichtlich generisch sind und für Array-ähnliche Objekte verwendet werden können, zArray.prototype.indexOf.call({0:'foo', 1:'bar', length: 2}, 'bar') == 1;
. Dasarguments
Objekt ist auch ein gutes Beispiel. Bei reinen Array-Objekten ist es unmöglich, den Typ derlength
Eigenschaft zu ändern , da sie eine spezielle interne [[Put
]] Methode implementieren. Wenn eine Zuweisung zurlength
Eigenschaft vorgenommen wird, wird diese erneut konvertiertToUint32
und es werden andere Aktionen ausgeführt, z. B. das Löschen der obigen Indizes die neue Länge ...Das ist der vorzeichenlose Rechtsbitverschiebungsoperator . Der Unterschied zwischen diesem und dem vorzeichenbehafteten Rechtsbitverschiebungsoperator besteht darin, dass der vorzeichenlose Rechtsbitverschiebungsoperator ( >>> ) mit Nullen von links und der vorzeichenbehaftete Rechtsbitverschiebungsoperator ( >> ) mit dem Vorzeichenbit gefüllt wird Beibehalten des Vorzeichens des numerischen Werts beim Verschieben.
quelle
>>>
wird in eine Ganzzahl konvertiert, was unary+
nicht tut.Driis hat ausreichend erklärt, was der Bediener ist und was er tut. Hier ist die Bedeutung dahinter / warum es verwendet wurde:
Shifting durch jede Richtung
0
tut kehrt die Zahl wieder und werfennull
zu0
. Es scheint, dass der Beispielcode, den Sie betrachten, verwendet wird,this.length >>> 0
um sicherzustellen, dass erlen
numerisch ist, auch wenn erthis.length
nicht definiert ist.Für viele Menschen sind bitweise Operationen unklar (und Douglas Crockford / jslint schlägt vor, solche Dinge nicht zu verwenden). Das bedeutet nicht, dass es falsch ist, aber es gibt günstigere und bekanntere Methoden, um Code lesbarer zu machen. Ein klarerer Weg, um dies sicherzustellen,
len
ist0
eine der beiden folgenden Methoden.oder
quelle
NaN
. ZB+{}
... Es ist wahrscheinlich am besten, die beiden zu kombinieren:+length||0
>>>
das ist unsigned rechtser Verschiebungsoperator ( vgl . S. 76 der JavaScript 1.5 - Spezifikation ), im Gegensatz zu dem>>
, dem signierten rechten Shift - Operator.>>>
Ändert die Ergebnisse der Verschiebung negativer Zahlen, da das Vorzeichenbit beim Verschieben nicht erhalten bleibt . Die Konsequenzen davon können anhand eines Dolmetschers anhand eines Beispiels verstanden werden: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
"cabbage"
obigen Beispiel. Ich denke in diesem Fall ist es sicher anzunehmen, dass diesthis.length
niemals der Fall sein wird< 0
. Trotzdem würde ich argumentieren, dass dieses Beispiel aus zwei Gründen ein böser Hack ist:Das Verhalten
<<<
bei Verwendung negativer Zahlen ist ein Nebeneffekt, der im obigen Beispiel wahrscheinlich nicht beabsichtigt ist (oder wahrscheinlich auftritt).Die Absicht des Codes ist nicht offensichtlich , wie die Existenz dieser Frage bestätigt.
Die beste Vorgehensweise besteht wahrscheinlich darin, etwas Lesbareres zu verwenden, es sei denn, die Leistung ist absolut kritisch:
quelle
-1 >>> 0
jemals eintreten und wenn ja, ist es wirklich wünschenswert, ihn auf 4294967295 zu verschieben? Scheint so, als würde die Schleife einige Male öfter als nötig ausgeführt.this.length
, ist es unmöglich zu wissen. Für jede "vernünftige" Implementierung sollte die Länge eines Strings niemals negativ sein, aber dann könnte man argumentieren, dass wir in einer "vernünftigen" Umgebung die Existenz einerthis.length
Eigenschaft annehmen können, die immer eine ganzzahlige Zahl zurückgibt.Zwei Gründe:
Das Ergebnis von >>> ist ein "Integral"
undefined >>> 0 = 0 (da JS versucht, das 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 verbessern.
Jedoch -1 >>> 0 (oops, wahrscheinlich keine gewünschte Länge!)
quelle
Der folgende Java-Beispielcode erklärt gut:
Die Ausgabe ist die folgende:
quelle