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

3715voto

stevehipwell Punkte 52558

Konvertiert Object a boolean . Wenn es falsch war (z. B. 0 , null , undefined usw.), wird es false , ansonsten, true .

!object  // inverted boolean
!!object // non inverted boolean so true boolean representation

Así que !! ist kein Operator, es ist nur die ! Betreiber zweimal.

Das kann einfacher sein:

Boolean(object) // boolean

Beispiel aus der Praxis "IE-Version testen":

const isIE8 = !! navigator.userAgent.match(/MSIE 8.0/);  
console.log(isIE8); // returns true or false 

Wenn Sie

console.log(navigator.userAgent.match(/MSIE 8.0/));  
// returns either an Array or null  

Aber wenn Sie

console.log(!!navigator.userAgent.match(/MSIE 8.0/));  
// returns either true or false

167 Stimmen

Es wandelt einen nicht booleschen Wert in einen invertierten booleschen Wert um (z. B. !5 wäre falsch, da 5 ein nicht-falscher Wert in JS ist), dann wird dieser boolesch invertiert, so dass man den ursprünglichen Wert als booleschen Wert erhält (!!5 wäre also wahr).

160 Stimmen

Das lässt sich leicht beschreiben: Boolean(5) === !!5; Gleiches Casting, weniger Zeichen.

62 Stimmen

Damit werden wahrheitsgemäße Werte in boolesches true und falsche Werte in boolesches false umgewandelt.

1032voto

Tom Ritter Punkte 97450

Das ist eine furchtbar obskure Art, eine Typkonvertierung durchzuführen.

! bedeutet ノット . Also !true es false y !false es true . !0 es true y !1 es false .

Sie wandeln also einen Wert in einen Booleschen Wert um, invertieren ihn dann und invertieren ihn wieder.

// Maximum Obscurity:
val.enabled = !!userId;

// Partial Obscurity:
val.enabled = (userId != 0) ? true : false;

// And finally, much easier to understand:
val.enabled = (userId != 0);

// Or just
val.enabled = Boolean(userId);

Anmerkung: die beiden letztgenannten Ausdrücke sind nicht genau gleichwertig mit dem ersten Ausdruck, wenn es um bestimmte Randfälle geht (wenn userId es [] zum Beispiel), aufgrund der Art und Weise, wie die != Operator funktioniert und welche Werte berücksichtigt werden wahrheitsgemäß .

112 Stimmen

!!false = falsch. !!true = true

139 Stimmen

Ist die "viel leichter zu verstehende" Variante hier wirklich viel leichter zu verstehen? Die Prüfung gegen 0 ist keine tatsächliche Prüfung gegen 0, sondern eine Prüfung gegen die etwas merkwürdige Liste von Werten, die Javascript als gleich 0 betrachtet. userId ? true : false macht deutlicher, dass eine Umwandlung stattfindet und behandelt den Fall, dass der Wert von userId explizit auf undefined

85 Stimmen

Mein Gehirn hat kein Problem mit der Entschlüsselung !!var en Boolean(var) und !! ist schneller (weniger Anweisungen zu verarbeiten) und kürzer als die Alternativen.

601voto

Salman A Punkte 246207

!!expr (zwei ! Operatoren gefolgt von einem Ausdruck) gibt einen booleschen Wert zurück ( true o false ) abhängig von der Wahrhaftigkeit des Ausdrucks. Es macht mehr Sinn, wenn es für nicht-boolesche Typen verwendet wird. Betrachten Sie diese Beispiele, vor allem das 3. und weitere:

          !!false === false
           !!true === true

              !!0 === false
!!parseInt("foo") === false // NaN is falsy
              !!1 === true
             !!-1 === true  // -1 is truthy
          !!(1/0) === true  // Infinity is truthy

             !!"" === false // empty string is falsy
          !!"foo" === true  // non-empty string is truthy
        !!"false" === true  // ...even if it contains a falsy value

     !!window.foo === false // undefined value is falsy
      !!undefined === false // undefined primitive is falsy
           !!null === false // null is falsy

             !!{} === true  // an (empty) object is truthy
             !![] === true  // an (empty) array is truthy; PHP programmers beware!

82 Stimmen

Das ist erwähnenswert: !!new Boolean(false) // true

60 Stimmen

...aber auch !!Boolean(false) // false

130 Stimmen

new Boolean(false) ist ein Objekt und ein Objekt ist wahr, auch wenn es einen falschen Wert enthält!

218voto

Benny Nightingale Punkte 2955

Brühen Sie einen Tee auf:

!! ist kein Operator. Es ist die doppelte Verwendung von ! -- das ist der logische "nicht"-Operator.


Theoretisch:

! bestimmt die "Wahrheit" dessen, was ein Wert nicht ist:

  • Die Wahrheit ist, dass false no es true (deshalb !false Ergebnisse in true )

  • Die Wahrheit ist, dass true no es false (deshalb !true Ergebnisse in false )


!! bestimmt die "Wahrheit" dessen, was ein Wert ist no nicht:

  • Die Wahrheit ist, dass true no es no true (deshalb !!true führt zu true )

  • Die Wahrheit ist, dass false no es no false (deshalb !!false führt zu false )


Was wir mit dem Vergleich feststellen wollen, ist die "Wahrheit". über den Wert einer Referenz, nicht den Wert von die Referenz selbst. Es gibt einen Anwendungsfall, in dem wir die Wahrheit über einen Wert wissen wollen, selbst wenn wir erwarten, dass der Wert false (oder falsch), oder wenn wir erwarten, dass der Wert nicht typeof ist boolean .


In der Praxis:

Betrachten wir eine prägnante Funktion, die die Funktionalität eines Merkmals (und in diesem Fall die Plattformkompatibilität) mit Hilfe von dynamische Schreibweise (auch bekannt als "Duck-Typing"). Wir wollen eine Funktion schreiben, die Folgendes zurückgibt true wenn der Browser eines Nutzers die HTML5 <audio> Element, aber wir wollen nicht, dass die Funktion einen Fehler auslöst, wenn <audio> undefiniert ist; und wir wollen nicht mit try ... catch um mit möglichen Fehlern umzugehen (weil sie grob sind); und auch wir wollen keine Prüfung innerhalb der Funktion verwenden, die nicht konsequent die Wahrheit über das Merkmal aufdeckt (z. B., document.createElement('audio') wird weiterhin ein Element namens <audio> auch wenn HTML5 <audio> wird nicht unterstützt).


Hier sind die drei Ansätze:

// this won't tell us anything about HTML5 `<audio>` as a feature
var foo = function(tag, atr) { return document.createElement(tag)[atr]; }

// this won't return true if the feature is detected (although it works just fine)
var bar = function(tag, atr) { return !document.createElement(tag)[atr]; }

// this is the concise, feature-detecting solution we want
var baz = function(tag, atr) { return !!document.createElement(tag)[atr]; }

foo('audio', 'preload'); // returns "auto"
bar('audio', 'preload'); // returns false
baz('audio', 'preload'); // returns true

Jede Funktion akzeptiert ein Argument für eine <tag> und ein attribute nach denen sie suchen, aber sie geben jeweils unterschiedliche Werte zurück, je nachdem, was die Vergleiche ergeben.

Aber halt, es gibt noch mehr!

Einige von Ihnen haben wahrscheinlich bemerkt, dass man in diesem speziellen Beispiel einfach nach einer Eigenschaft suchen könnte, indem man die leicht leistungsfähiger Mittel zur Überprüfung, ob das betreffende Objekt hat eine Eigenschaft. Es gibt zwei Möglichkeiten, dies zu tun:

// the native `hasOwnProperty` method
var qux = function(tag, atr) { return document.createElement(tag).hasOwnProperty(atr); }

// the `in` operator
var quux = function(tag, atr) { return atr in document.createElement(tag); }

qux('audio', 'preload');  // returns true
quux('audio', 'preload'); // returns true

Wir schweifen ab...

Wie selten diese Situationen auch sein mögen, so gibt es doch einige wenige Szenarien, in denen das prägnanteste, leistungsfähigste und somit bevorzugte Mittel, um true von einem nicht-booleschen, möglicherweise undefinierten Wert ist in der Tat durch die Verwendung von !! . Ich hoffe, das klärt die Sache lächerlich auf.

9 Stimmen

Total geniale Antwort, aber ich sehe den Nutzen des Konstrukts !! nicht. Da ein if() Anweisung den Ausdruck bereits in einen booleschen Wert umwandelt, ist es überflüssig, den Rückgabewert einer Prüffunktion explizit in einen booleschen Wert umzuwandeln - da "Wahrhaftigkeit" === wahr ist, soweit eine if() Aussage geht trotzdem. Oder übersehe ich ein Szenario, in dem Sie einen wahrheitsgemäßen Ausdruck benötigen, um tatsächlich boolesch zu sein true ?

6 Stimmen

@TomAuger if() Anweisungen setzen boolesche gegen falsche Werte, aber sagen wir, Sie wollen tatsächlich ein boolesches Flag auf ein Objekt setzen - es wird nicht wie ein if() Anweisung tut. Zum Beispiel object.hasTheThing = !!castTheReturnValToBoolNoMatterWhat() würde entweder true o false anstelle des tatsächlichen Rückgabewerts. Ein anderes Beispiel ist vielleicht, dass alle Admins id de 0 und Nicht-Admins sind id 1 oder höher. Um zu true Wenn jemand kein Administrator ist, können Sie Folgendes tun person.isNotAdmin = !!admin.id . Wenige Anwendungsfälle, aber es ist prägnant, wenn es welche gibt.

122voto

Crescent Fresh Punkte 111444

!! wandelt den Wert rechts davon in seinen entsprechenden booleschen Wert um. (Denken Sie an die "Typisierung" des armen Mannes). Sein Absicht ist in der Regel, um dem Leser zu vermitteln, dass der Code nicht interessiert was Wert in der Variable ist, sondern was sie ist Wert "Wahrheit" ist.

6 Stimmen

Im Falle eines booleschen Wertes auf der rechten Seite geschieht nichts.

4 Stimmen

@Daniel: ! spiegelt den Wert immer noch nach rechts. Im Falle eines booleschen Wertes wird der ganz rechts stehende ! negiert den Wert, während der ganz links stehende ! verneint sie erneut. Der Nettoeffekt ist, dass es keine Änderung gibt, aber die meisten Motoren erzeugen Op-Codes für die doppelte Negation.

0 Stimmen

Aber was ist der Sinn? Wenn ich das tue if(0){... Javascript weiß bereits, dass dies falsch ist. Warum ist es besser zu sagen if(!!0){... ?

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