4186 Stimmen

Was ist der !! (nicht nicht) Operator in JavaScript?

Ich habe einen Code gesehen, der einen mir unbekannten Operator in Form von zwei Ausrufezeichen zu verwenden scheint, etwa so: !! . Kann mir bitte jemand sagen, was dieser Operator macht?

Der Kontext, in dem ich dies sah, war,

this.vertical = vertical !== undefined ? !!vertical : this.vertical;

1428 Stimmen

Erinnern Sie sich daran mit "bang, bang, du bist boolesch"

126 Stimmen

Nur um das festzuhalten: Tun Sie nicht, was dort steht. Machen Sie if(vertical !== undefined) this.vertical = Boolean(vertical); - es ist viel sauberer und klarer, was vor sich geht, erfordert keine unnötige Zuweisung, ist ganz Standard und ist genauso schnell (auf aktuellem FF und Chrome) jsperf.com/boolean-conversion-speed .

0 Stimmen

"Jeder anständige Programmierer sollte wissen, was vor sich geht..." - manchmal hilft es dem Compiler, besseren Code in kompilierten Sprachen zu erzeugen. Ich weiß, dass es früher von Microsoft bei der Verwendung von C-Code empfohlen wurde, weil es den besten Code erzeugt. (Wahrscheinlich wird es immer noch empfohlen, aber ich kann die Referenz im Moment nicht finden).

95voto

ruffin Punkte 14815

So viele Antworten machen die halbe Arbeit. Ja, !!X könnte als "die Wahrhaftigkeit von X [dargestellt als Boolescher Wert]" gelesen werden. Aber !! ist, praktisch gesehen, nicht so wichtig, um herauszufinden, ob eine einzelne Variable (oder sogar mehrere Variablen) wahr oder falsch ist. !!myVar === true ist dasselbe wie nur myVar . Vergleich von !!X in einen "echten" Booleschen Wert umzuwandeln, ist nicht wirklich nützlich.

Das Einzige, was Sie gewinnen, wenn Sie !! ist die Fähigkeit, den Wahrheitsgehalt mehrerer Variablen zu überprüfen gegeneinander in einer wiederholbaren, standardisierten (und JSLint-freundlichen) Weise.

Einfach gießen :(

Das heißt...

  • 0 === false es false .
  • !!0 === false es true .

Die obigen Angaben sind nicht so nützlich. if (!0) liefert die gleichen Ergebnisse wie if (!!0 === false) . Mir fällt kein guter Grund ein, eine Variable in einen booleschen Wert umzuwandeln und dann mit einem booleschen Wert "true" zu vergleichen.

Siehe "== und !=" aus JSLint's Wegbeschreibung (Anmerkung: Crockford ist dabei, seine Website ein wenig zu verschieben; dieser Link wird wahrscheinlich irgendwann verschwinden), um ein wenig über die Gründe zu erfahren:

Die Operatoren == und != führen vor dem Vergleich eine Typenzerlegung durch. Das ist schlecht, denn es verursacht ' \t\r\n ' == 0 wahr sein. Dies kann Typfehler maskieren. JSLint kann nicht zuverlässig feststellen, ob == korrekt verwendet wird, daher ist es am besten, == und != überhaupt nicht zu verwenden und stattdessen immer die zuverlässigeren Operatoren === und !== zu benutzen.

Wenn es Ihnen nur darum geht, ob ein Wert wahr oder falsch ist, dann verwenden Sie die Kurzform. Anstelle von
(foo != 0)

nur sagen
(foo)

und anstelle von
(foo == 0)

sagen
(!foo)

Beachten Sie, dass es einige unintuitive Fälle wobei ein boolescher Wert in eine Zahl umgewandelt wird ( true wird geworfen auf 1 y false a 0 ), wenn ein boolescher Wert mit einer Zahl verglichen wird. In diesem Fall, !! geistig nützlich sein könnte. Obwohl, noch einmal, Dies sind Fälle, in denen Sie einen Nicht-Booleschen mit einem hart getippten Booleschen vergleichen, was imo ein schwerer Fehler ist. if (-1) ist hier nach wie vor der richtige Weg.

               Original                    Equivalent       Result   

 if (-1 == true) console.log("spam")    if (-1 == 1)       undefined 
 if (-1 == false) console.log("spam")   if (-1 == 0)       undefined 
   Order doesn't matter...                                           
 if (true == -1) console.log("spam")    if (1 == -1)       undefined 

 if (!!-1 == true) console.log("spam")  if (true == true)  spam       better

 if (-1) console.log("spam")            if (truthy)        spam       still best

Und je nach Motor werden die Dinge noch verrückter. WScript, zum Beispiel, gewinnt den Preis.

function test()
{
    return (1 === 1);
}
WScript.echo(test());

Wegen der einige historische Windows-Sprüche wird in einem Nachrichtenfeld -1 ausgegeben! Versuchen Sie es in einer cmd.exe-Eingabeaufforderung und sehen Sie nach! Aber WScript.echo(-1 == test()) ergibt immer noch 0, oder WScripts false . Schauen Sie weg. Es ist abscheulich.

Wahrhaftigkeit im Vergleich :)

Was aber, wenn ich zwei Werte habe, die ich auf gleiche Wahrhaftigkeit/Falschheit prüfen muss?

Nehmen wir an, wir haben myVar1 = 0; y myVar2 = undefined; .

  • myVar1 === myVar2 es 0 === undefined und ist offensichtlich falsch.
  • !!myVar1 === !!myVar2 es !!0 === !!undefined und ist wahr! Gleiche Wahrhaftigkeit! (In diesem Fall haben beide "einen Wahrheitsgehalt von falsy".)

Der einzige Ort, an dem Sie wirklich "boolesche Variablen" verwenden müssten, wäre eine Situation, in der Sie prüfen, ob beide Variablen die dieselbe Wahrhaftigkeit, richtig? Das heißt, utiliser !! wenn Sie sehen müssen, ob zwei Variablen gleich sind beide wahrheitsgemäß oder beide falsch (oder nicht), das heißt, von gleicher (oder auch nicht) Wahrhaftigkeit .

Mir fällt auf Anhieb kein großartiger, ungekünstelter Anwendungsfall dafür ein. Vielleicht haben Sie "verknüpfte" Felder in einem Formular?

if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
    errorObjects.spouse = "Please either enter a valid name AND age " 
        + "for your spouse or leave all spouse fields blank.";
}

Wenn Sie also eine Wahrheit für beide haben o ein falsches Feld für den Namen des Ehepartners und das Alter, können Sie fortfahren. Andernfalls haben Sie nur ein Feld mit einem Wert (oder eine sehr früh arrangierte Ehe) und müssen einen zusätzlichen Fehler in Ihrer errorObjects Sammlung.

Aber auch in diesem Fall ist die !! ist wirklich überflüssig. Eine ! genügte, um in einen Booleschen Wert umzuwandeln, und Sie prüfen nur die Gleichheit.


EDIT 24 Oct 2017, 6 Feb 19:

Bibliotheken von Drittanbietern, die explizite boolesche Werte erwarten

Hier ist ein interessanter Fall... !! kann nützlich sein, wenn Bibliotheken von Drittanbietern explizite boolesche Werte erwarten.

Reagieren Sie

Zum Beispiel, False in JSX (React) hat eine besondere Bedeutung die nicht durch einfache Falschheit ausgelöst wird. Wenn Sie versucht, die Rückgabe etwas wie das folgende in Ihrem JSX, erwarten eine int in messageCount ...

{messageCount && <div>You have messages!</div>}

... werden Sie vielleicht überrascht sein, dass React eine 0 wenn Sie keine Nachrichten haben. Sie müssen explizit false zurückgeben, damit JSX nicht gerendert wird. Die obige Anweisung gibt 0 die JSX fröhlich wiedergibt, wie es sich gehört. Es kann nicht sagen, dass Sie nicht haben Count: {messageCount} .

  • Eine Lösung ist der "Bangbang", der die Menschen dazu zwingt 0 in !!0 que es false :
    {!!messageCount && <div>You have messages!</div>}

  • JSX' docs empfehlen Sie expliziter sein, schreiben selbst-kommentierenden Code, und verwenden Sie einen Vergleich zu einem Boolean zu erzwingen.
    {messageCount > 0 && <div>You have messages!</div>}

  • Ich selbst komme mit Falschheit besser zurecht, wenn ich eine ternäre --
    {messageCount ? <div>You have messages!</div> : false}

Typoskript

Dasselbe gilt für Typescript: Wenn Sie eine Funktion haben, die einen booleschen Wert zurückgibt (oder Sie weisen einer booleschen Variablen einen Wert zu), können Sie [normalerweise] keinen booleschen Wert zurückgeben/zuweisen; es muss ein stark typisierter boolescher Wert sein. Dies bedeutet, wenn myObject stark typisiert ist , return !myObject; funktioniert für eine Funktion, die einen booleschen Wert zurückgibt, aber return myObject; nicht. Sie müssen return !!myObject (oder auf andere Weise in den richtigen Booleschen Wert umwandeln), um die Erwartungen von Typescript zu erfüllen.

Die Ausnahme für Typescript? Wenn myObject war ein any sind Sie zurück im Wilden Westen von JavaScript und können es ohne !!, even if your return type is a boolean.

``

Keep in mind that these are JSX & Typescript conventions, not ones inherent to JavaScript.

But if you see strange 0s in your rendered JSX, think loose falsy management.

``

1 Stimmen

Gute Erklärung. Würden Sie also sagen, dass das !! in diesem Fall nicht unbedingt notwendig ist? Erkennung von Arbeitnehmermerkmalen Beispiel? if (!!window.Worker)

3 Stimmen

Nein, das brauchen Sie nicht. Wahrhaftigkeit und true "extern" genau dasselbe in einer if . Ich versuche es immer wieder, aber mir fällt kein Grund ein, die Wahrhaftigkeit in einen booleschen Wert umzuwandeln, abgesehen von dem oben beschriebenen Fall des "Vergleichens von Wahrhaftigkeiten", außer aus Gründen der Lesbarkeit, wenn Sie den Wert später wiederverwenden, wie in der q Beispiel einer Bibliothek. Aber selbst dann handelt es sich um eine informationsarme Abkürzung, und ich würde behaupten, dass es besser ist, den Wahrheitsgehalt jedes Mal neu zu bewerten.

95voto

Christoph Punkte 157217

!!foo wendet den unären not-Operator zweimal an und wird zur Umwandlung in einen booleschen Typ verwendet, ähnlich wie bei der Verwendung des unären plus +foo in eine Zahl umzuwandeln und eine leere Zeichenkette zu verketten ''+foo in eine Zeichenkette umzuwandeln.

Anstelle dieser Hacks können Sie auch die Konstruktorfunktionen verwenden, die den primitiven Typen entsprechen ( ohne mit new ), um Werte explizit zu casten, d.h.

Boolean(foo) === !!foo
Number(foo)  === +foo
String(foo)  === ''+foo

0 Stimmen

Aber dann kann es zu Problemen mit instanceof kommen. new Boolean(1) instanceof Object -> true !!1 instanceof Object -> false

17 Stimmen

Nein, das kann man nicht: Die Konstruktorfunktionen werden ohne new - wie in meiner Antwort ausdrücklich erwähnt

3 Stimmen

Fantastisch! Dies ist nützlich für einen kleinen Hack, wenn Sie Strings mit "0" als falsch statt als wahr auswerten müssen (z.B. beim Lesen von Werten aus Selects, da diese als String gelesen werden). Wenn Sie also "0" als negativ (Boolean false) betrachten wollen, nehmen Sie an x="0" einfach tun: x=!!+x; //false was dasselbe ist wie Boolean(Number(x)) Number (oder +x) wandelt die Zeichenkette "0" in 0 um, was den Wert false ergibt, und Boolean (!!x) wandelt sie direkt in boolean um. Kinderleicht!

68voto

Greg Punkte 306033

Es ist nur der logische NOT-Operator, zweimal - er wird verwendet, um etwas in einen booleschen Wert umzuwandeln, z.B.:

true === !!10

false === !!0

36voto

Paul McMillan Punkte 19166

Sie wandelt das Suffix in einen booleschen Wert um.

33voto

Steve Harrison Punkte 111024

Es scheint, dass die !! Operator führt zu einer doppelten Negation.

var foo = "Hello World!";

!foo // Result: false
!!foo // Result: true

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X