Wer hätte gedacht, dass die seltenen und geheimnisvollen bitweisen Operatoren von JavaScript so nützlich sein könnten? Ich habe diesen Trick zum ersten Mal vor einer Weile in einer Slideshow zur JavaScript-Performance von Thomas Fuchs entdeckt. Der „Trick“ lautet wie folgt:
Der bitweise NOT-Operator (~
) nimmt seinen Operanden, konvertiert ihn in eine 32-Bit-Ganzzahl und invertiert dann jedes Bit, sodass jedes 0
zu einer 1
und umgekehrt wird.
00000000000000000000000000001001 ...wird zu 11111111111111111111111111110110
Die Wirkung davon, wenn der Ausdruck ~foo
gegeben ist, ist -(foo + 1)
. Eine doppelte bitweise NICHT-Operation (~~foo
) führt daher zu -(-(foo + 1) + 1)
. Dies bleibt jedoch nur für Ganzzahlen wahr; bei allen potenziellen Operanden ist der tatsächliche äquivalente Ausdruck zu ~~
wahrscheinlich etwas wie:
typeof foo === 'number' && !isNaN(foo) && foo !== Infinity ? foo > 0 ? Math.floor(foo) : Math.ceil(foo) : 0; // Das ist NUR effektiv dasselbe... das ist // NICHT das, was intern passiert!
Das ist offensichtlich ein ziemlich langsamer als ~~
.
Wenn das Operand eine Zahl ist und nicht NaN
oder Infinity
ist, dann wird ~~
den Effekt haben, sie zur Null zu runden (Math.ceil
für negative, Math.floor
für positive). Wenn es keine Zahl ist, dann glaube ich, dass die interne ToInt32
-Funktion sie in Null umwandelt.
Hier sind einige Beispiele für die doppelte bitweise NICHT-Operation in all ihrer Pracht:
~~null; // => 0 ~~undefined; // => 0 ~~0; // => 0 ~~{}; // => 0 ~~[]; // => 0 ~~(1/0); // => 0 ~~false; // => 0 ~~true; // => 1 ~~1.2543; // => 1 ~~4.9; // => 4 ~~(-2.999); // => -2
~~
‘s flooring capabilities make it a better alternative to Math.floor
if you know you’re dealing with positives — it’s faster and takes up less characters. It’s not quite as readable though, but I’m hoping that ~~
will slowly become a very well-known technique in the JS arena, so we can all use it without fearing accusations.
Es ist ziemlich nützlich, um Argumente zu normalisieren, von denen Sie erwarten, dass sie auch Ganzzahlen sind. Nehmen Sie dieses Beispiel von dem, was die MDC empfiehlt für die Bereitstellung von Array.prototype.indexOf
für nicht unterstützende Browser:
/Array.prototype.indexOf = function.../ var from = Number(arguments[1]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from);