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).

15voto

Damian Yerrick Punkte 4424

El if y while Aussagen und die ? Operator verwenden Wahrheitswerte, um zu bestimmen, welcher Zweig des Codes ausgeführt werden soll. So sind beispielsweise die Zahlen Null und NaN sowie die leere Zeichenkette falsch, während andere Zahlen und Zeichenketten wahr sind. Objekte sind wahr, aber der undefinierte Wert und null sind beide falsch.

Der doppelte Negationsoperator !! errechnet den Wahrheitswert eines Wertes. Es sind eigentlich zwei Operatoren, wobei !!x bedeutet !(!x) und verhält sich wie folgt:

  • Wenn x ist ein falscher Wert, !x es true y !!x es false .
  • Wenn x ist ein echter Wert, !x es false y !!x es true .

Bei Verwendung auf der obersten Ebene eines booleschen Kontexts ( if , while , oder ? ), die !! Operator ist verhaltenstechnisch ein No-op. Zum Beispiel, if (x) y if (!!x) das Gleiche bedeuten.

Praktische Anwendungen

Es hat jedoch mehrere praktische Anwendungen.

Eine Möglichkeit besteht darin, ein Objekt verlustbehaftet auf seinen wahren Wert zu komprimieren, so dass Ihr Code keinen Verweis auf ein großes Objekt enthält und dieses am Leben erhält. Zuweisung von !!some_big_object in eine Variable anstelle von some_big_object lässt es für den Garbage Collector los. Dies ist nützlich für Fälle, die entweder ein Objekt oder einen falschen Wert erzeugen, wie z.B. null oder den undefinierten Wert, wie z. B. die Erkennung von Browser-Features.

Eine weitere Verwendung, die ich in einem Antwort über C's entsprechende !! operador ist mit "lint"-Werkzeugen, die nach häufigen Tippfehlern suchen und Diagnosen ausgeben. Sowohl in C als auch in JavaScript führen beispielsweise einige häufige Tippfehler bei booleschen Operationen zu anderen Verhaltensweisen, deren Ausgabe nicht ganz so boolesch ist:

  • if (a = b) ist eine Zuweisung, gefolgt von der Verwendung des Wahrheitswertes von b ; if (a == b) ist ein Gleichheitsvergleich.
  • if (a & b) ist ein bitweises UND; if (a && b) ist ein logisches UND. 2 & 5 es 0 (ein falscher Wert); 2 && 5 wahr ist.

El !! Operator versichert dem Lint-Tool, dass das, was Sie geschrieben haben, das ist, was Sie gemeint haben: Führe diese Operation durch und nimm dann den Wahrheitswert des Ergebnisses.

Eine dritte Verwendung ist die Erzeugung von logischem XOR und logischem XNOR. Sowohl in C als auch in JavaScript, a && b führt eine logische UND-Verknüpfung durch (wahr, wenn beide Seiten wahr sind), und a & b führt ein bitweises AND durch. a || b führt eine logische ODER-Verknüpfung durch (wahr, wenn mindestens eine der beiden Antworten wahr ist), und a | b führt ein bitweises ODER durch. Es gibt ein bitweises XOR (exklusives OR) als a ^ b , aber es gibt keinen eingebauten Operator für logisches XOR (wahr, wenn genau eine Seite wahr ist). Sie könnten zum Beispiel dem Benutzer erlauben, Text in genau eines von zwei Feldern einzugeben. Sie können jedes Feld in einen Wahrheitswert umwandeln und vergleichen: !!x !== !!y .

12voto

Sergey Ilinsky Punkte 30525

Doppelte boolesche Verneinung. Wird oft verwendet, um zu prüfen, ob der Wert nicht undefiniert ist.

12voto

Ryan Taylor Punkte 10733

Ich wollte nur hinzufügen, dass

if(variableThing){
  // do something
}

ist dasselbe wie

if(!!variableThing){
  // do something
}

Dies kann jedoch ein Problem sein, wenn etwas nicht definiert ist.

// a === undefined, b is an empty object (eg. b.asdf === undefined)
var a, b = {};

// Both of these give error a.foo is not defined etc.
// you'd see the same behavior for !!a.foo and !!b.foo.bar

a.foo 
b.foo.bar

// This works -- these return undefined

a && a.foo
b.foo && b.foo.bar
b && b.foo && b.foo.bar

Der Trick dabei ist die Kette von && s wird zurückkehren der erste falsche Wert und dies kann in eine if-Anweisung usw. eingespeist werden. Wenn also b.foo undefiniert ist, gibt es undefiniert zurück und überspringt die b.foo.bar Anweisung, und wir erhalten keinen Fehler.

Die oben genannten geben undefiniert zurück, aber wenn Sie eine leere Zeichenkette, false, null, 0, undefiniert haben, werden diese Werte zurückgegeben, sobald wir sie in der Kette finden. [] y {} sind beide "wahrheitsgemäß", und wir setzen die so genannte "&&-Kette" bis zum nächsten Wert auf der rechten Seite fort.

P.S. Eine andere Möglichkeit, das oben genannte zu tun ( b && b.foo ) ist (b || {}).foo . Diese sind äquivalent, denn wenn b undefiniert ist, dann b || {} wird sein {} und Sie werden auf einen Wert in einem leeren Objekt zugreifen (kein Fehler), anstatt zu versuchen, auf einen Wert in "undefined" zuzugreifen (verursacht einen Fehler).

Also, (b || {}).foo ist dasselbe wie b && b.foo y ((b || {}).foo || {}).bar ist dasselbe wie b && b.foo && b.foo.bar .

0 Stimmen

Gutes Argument - ich habe meine Antwort geändert. Es passiert nur bei einem Objekt, wenn es drei Ebenen tief verschachtelt ist, denn wie Sie sagten ({}).anything wird geben undefined

11voto

Warren Davis Punkte 313

Hier gibt es viele tolle Antworten, aber wenn Sie bis hierher gelesen haben, hat mir das geholfen. Öffnen Sie die Konsole in Chrome (usw.) und beginnen Sie zu tippen:

!(!(1))
!(!(0))
!(!('truthy')) 
!(!(null))
!(!(''))
!(!(undefined))
!(!(new Object())
!(!({}))
woo = 'hoo'
!(!(woo))
...etc, etc, until the light goes on ;)

Natürlich ist das alles dasselbe wie die Eingabe von !!someThing, aber die zusätzlichen Klammern machen es vielleicht verständlicher.

11voto

Greg Gum Punkte 29158

!!x ist die Kurzform für Boolean(x)

Der erste Knall zwingt den js-Motor zum Laufen Boolean(x) hat aber auch den Nebeneffekt, dass der Wert invertiert wird. Der zweite Knall macht diesen Nebeneffekt also wieder rückgängig.

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