wake-up-neo.com

Operator-Rangfolge mit dem ternären Javascript-Operator

Ich kann nicht scheinen, meinen Kopf um den ersten Teil dieses Codes (+ =) in Kombination mit dem ternären Operator zu wickeln.

h.className += h.className ? ' error' : 'error'

Ich denke, dieser Code funktioniert folgendermaßen:

h.className = h.className + h.className ? ' error' : 'error'

Aber das ist nicht richtig, weil das einen Fehler in meiner Konsole gibt.

Meine Frage ist also, wie ich diesen Code richtig einfügen soll.

116
Baijs
h.className = h.className + (h.className ? ' error' : 'error')

Sie möchten, dass der Operator für h.className Arbeitet, genauer gesagt.
Natürlich sollte h.className += ' error' Keinen Schaden anrichten, aber das ist eine andere Sache.

Beachten Sie auch, dass + Vorrang vor dem ternären Operator hat: JavaScript Operator Precedence

141
Kobi

Denk darüber so:

<variable> = <expression> ? <true clause> : <false clause>

Die Art und Weise, wie die Anweisung ausgeführt wird, ist im Wesentlichen wie folgt:

  1. Wird <expression> Als wahr oder als falsch bewertet?
  2. Wenn <expression> Als wahr ausgewertet wird, wird der Wert von <true clause><variable> Zugewiesen, <false clause> Wird ignoriert und die nächste Anweisung wird ausgeführt.
  3. Wenn <expression> Als falsch ausgewertet wird, wird <true clause> Ignoriert und der Wert von <false clause> Wird <variable> Zugewiesen.

Wichtig für den ternären Operator in dieser und anderen Sprachen ist, dass der Code in <expression> Bei der Auswertung ein boolesches Ergebnis liefert: entweder wahr oder falsch.

Im Fall Ihres Beispiels ersetzen Sie "zugewiesen zu" in meiner Erläuterung durch "hinzugefügt zu" oder Ähnliches für die von Ihnen verwendete Kurzarithmetik, falls vorhanden.

129
Wayne Koorts

Das += macht, was Sie wollen, aber in der ternären Anweisung rechts davon wird geprüft, ob h.className ist falsch, was es wäre, wenn es undefiniert wäre. Wenn es wahr ist (d. H. Wenn ein Klassenname bereits angegeben ist), wird ein Fehler mit einem Leerzeichen hinzugefügt (d. H. Hinzufügen einer neuen Klasse), andernfalls wird es ohne das Leerzeichen hinzugefügt.

Der Code könnte wie von Ihnen vorgeschlagen umgeschrieben werden, aber Sie müssen angeben, dass h.className soll für den Wahrheitsvergleich und nicht für die Verwendung des tatsächlichen Werts im ternären Operator verwendet werden. Achten Sie also darauf, dass Sie sich nicht gleichzeitig mit Ihrer ternären Operation mit der Verkettung von Werten befassen:

h.className = h.className + (h.className ? ' error' : 'error');
10
David Hedlund

Die rechte Seite des = Operator wird von links nach rechts ausgewertet. So,

g.className = h.className + h.className ? ' error' : 'error';`

ist äquivalent zu

h.className = (h.className + h.className) ? ' error' : 'error';

Äquivalent zu sein

h.className += h.className ? ' error' : 'error';

sie müssen die ternäre Anweisung in Klammern trennen

h.className = h.className + (h.className ? ' error' : 'error');
4
Justin Johnson
if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

sollte gleich sein mit:

h.className += h.className ? ' error' : 'error';
3
Darin Dimitrov

Ich würde gerne eine Erklärung von Wayne auswählen:

<variable> = <expression> ? <true clause> : <false clause>

Betrachten wir beide Fälle:

case 1:
h.className += h.className ? 'true' : 'false'     
  • der Zuweisungsoperator funktioniert einwandfrei und der Wert wird angehängt
  • wenn es zum ersten Mal ausgeführt wird, ist o/p: false
  • 2. Mal. o/p: falsetrue - Werte werden weiterhin angehängt

case2: h.className = h.className + h.className? 'wahr falsch'

  • das Ergebnis ist nicht dasselbe wie in Fall 1
  • wenn es zum ersten Mal ausgeführt wird, ist o/p: false
  • 2. Mal. o/p: false - Werte werden nicht immer angehängt

explanation

Im obigen Code funktioniert Fall 1 einwandfrei

während case2:

h.className = h.className + h.className ? 'true' : 'false'
is executed as 
 h.className = (h.className + h.className) ? 'true' : 'false'

h.className + h.className => als Ausdruck für ternären Operator betrachtet, da ternären Operator eine höhere Priorität eingeräumt wird. Daher wird immer nur das Ergebnis des ternären Ausdrucks zugewiesen

Sie müssen den Vorrang mithilfe von Klammern definieren

Sie müssen die Auswertungsreihenfolge definieren, die mit Hilfe von Klammern berücksichtigt werden soll, damit Fall 2 wie Fall 1 funktioniert

h.className = h.className + (h.className ? ' error' : 'error') 
1
Angelin Nadar

Ich weiß, dass dies eine sehr alte Frage ist, aber ich bin mit keiner der Antworten zu 100% zufrieden, da sie alle unvollständig zu sein scheinen. Also los gehts nochmal von den ersten Schulleitern:

Das allgemeine Ziel des Benutzers:

Zusammenfassung des Codes: "Ich möchte einem String einen error-Klassennamen hinzufügen, optional mit einem führenden Leerzeichen, wenn der String bereits Klassennamen enthält."

Einfachste Lösung

Wie Kobi vor 5 Jahren betonte, wird ein führendes Leerzeichen in Klassennamen mit keinem bekannten Browser Probleme bereiten. Die kürzeste richtige Lösung wäre also:

h.className += ' error';

Das hätte die tatsächliche Antwort sein sollen auf das tatsächliche Problem.


Wie dem auch sei, die gestellten Fragen waren ...

1) Warum hat das funktioniert?

h.className += h.className ? ' error' : 'error'

Der bedingte/ternäre Operator funktioniert wie eine if-Anweisung, die einer Variablen das Ergebnis ihrer Pfade true oder false zuweist.

Dieser Code hat also funktioniert, weil er einfach wie folgt ausgewertet wird:

if (h.className IS NOT null AND IS NOT undefined AND IS NOT '') 
    h.className += ' error'
else
    h.className += 'error'

2) und warum ist das kaputt gegangen?

h.className = h.className + h.className ? ' error' : 'error'

Die Frage besagt "das gibt einen [n] Fehler in meiner Konsole", der Sie in die Irre führen kann, wenn Sie den Code denken funktioniert nicht. Tatsächlich läuft der folgende Code ohne Fehler, gibt aber einfach 'Fehler' zurück, wenn der String war nicht leer und 'Fehler', wenn der String = war leer und so hat die Anforderungen nicht erfüllt.

Dieser Code führt immer zu einer Zeichenfolge, die nur ' error' Oder 'error' Enthält, da er diesen Pseudocode ergibt:

if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
    h.className = ' error'
else
    h.className = 'error'

Der Grund dafür ist, dass der Additionsoperator (+ Zum Common Folk) eine höhere "Priorität" (6) hat als der bedingte/ternäre Operator (15). Ich weiß, dass die Zahlen rückwärts erscheinen

Vorrang bedeutet einfach, dass jeder Operatortyp in einer Sprache in einer bestimmten vordefinierten Reihenfolge (und nicht nur von links nach rechts) ausgewertet wird.

Referenz: Priorität des Javascript-Operators

So ändern Sie die Reihenfolge der Auswertung:

Jetzt wissen wir, warum es fehlschlägt. Sie müssen wissen, wie es funktioniert.

Einige andere Antworten sprechen von Ändern der Priorität, aber Sie können nicht. Der Vorrang ist fest mit der Sprache verbunden. Das ist nur ein fester Satz von Regeln ... Sie können jedoch die Reihenfolge der Auswertung ändern ...

Das Werkzeug in unserer Toolbox, das die Reihenfolge der Auswertung ändern kann ist der Gruppierungsoperator (auch als Klammern bezeichnet). Dies geschieht, indem sichergestellt wird, dass die Ausdrücke in den Klammern vor Operationen außerhalb der Klammern ausgewertet werden. Das ist alles was sie tun, aber das ist genug.

Klammern funktionieren einfach, weil sie (Gruppierungsoperatoren) Vorrang haben als alle anderen Operatoren ("es gibt jetzt eine Stufe 0").

Durch einfaches Hinzufügen von Klammern können Sie die Reihenfolge der Auswertung ändern sicherstellen, dass der bedingte Test zuerst ausgeführt wird, bevor die einfache Verkettung von Zeichenfolgen erfolgt:

h.className = h.className + (h.className ? ' error' : 'error')

Ich überlasse diese Antwort jetzt Rust unsichtbar unter den anderen:)

1
Gone Coding