priorité de l'opérateur avec JavaScript opérateur ternaires
Question
Je ne peux pas semble envelopper ma tête autour de la première partie de ce code (+ =) en combinaison avec l'opérateur ternaire.
h.className += h.className ? ' error' : 'error'
La façon dont je pense que ce code fonctionne est comme suit:
h.className = h.className + h.className ? ' error' : 'error'
Mais ce n'est pas correct parce que cela donne une erreur dans ma console.
Alors, ma question est de savoir comment dois-je Interpet ce code correctement?
La solution
h.className = h.className + (h.className ? ' error' : 'error')
Vous voulez que l'opérateur de travailler pour h.className
, mieux être précis à ce sujet.
Bien sûr, aucun mal ne devrait provenir h.className += ' error'
, mais c'est une autre affaire.
Notez également que +
a priorité sur l'opérateur ternaire: JavaScript opérateur précédence
Autres conseils
Pensez-y de cette façon:
<variable> = <expression> ? <true clause> : <false clause>
La façon dont la déclaration est exécuté est essentiellement comme suit:
- Est-ce que
<expression>
évaluer true, ou faut-il évaluer false? - Si
<expression>
évalue à true, alors la valeur de<true clause>
est affecté à<variable>
,<false clause>
est ignorée, et l'instruction suivante est exécutée. - Si
<expression>
évalue à false,<true clause>
est ignorée et la valeur de<false clause>
est affecté à<variable>
.
La chose importante à réaliser avec l'opérateur ternaire dans ce domaine et d'autres langues est que quel que soit le code est en <expression>
devrait produire un résultat booléen lorsqu'il est évalué: true ou false
Dans le cas de votre exemple remplacer « attribué à » dans mon explication avec « ajouté à », ou similaire pour l'arithmétique selon un raccourci que vous utilisez, le cas échéant.
Le +=
fait ce que vous voulez, mais dans la déclaration ternaire à la main droite de celui-ci, il vérifie si h.className
est Falsey, qu'il serait si elle était définie. Si c'est truthy (à savoir si un nom de classe est déjà spécifié), puis l'erreur est ajouté avec un espace (par exemple l'ajout d'un nouveau classe), sinon il est ajouté sans l'espace.
Le code pourrait être réécrite comme vous le suggérez, mais vous devez préciser que h.className
doit être utilisé pour truthiness de comparaison, plutôt que pour l'utilisation de sa valeur réelle, dans l'opérateur ternaire, alors assurez-vous ne vous préoccupez pas la concaténation des valeurs en même temps que faire votre opération ternaire:
h.className = h.className + (h.className ? ' error' : 'error');
Le côté droit de l'opérateur =
est évaluée à gauche à droite. Ainsi,
g.className = h.className + h.className ? ' error' : 'error';`
est équivalent à
h.className = (h.className + h.className) ? ' error' : 'error';
Pour être équivalent à
h.className += h.className ? ' error' : 'error';
vous devez séparer la déclaration ternaire entre parenthèses
h.className = h.className + (h.className ? ' error' : 'error');
if (h.className) {
h.className = h.className + ' error';
} else {
h.className = h.className + 'error';
}
devrait être équivalent:
h.className += h.className ? ' error' : 'error';
Je sais que c'est une question très ancienne, mais je ne suis pas satisfait à 100% avec l'une des réponses que tous semblent incomplètes. Alors on y va à nouveau de premiers principes:
objectif global de l'utilisateur:
Résumant le code: «Je veux ajouter un nom de classe error
à une chaîne, éventuellement avec un espace de premier plan s'il y a des noms déjà classe dans la chaîne »
solution Simplest
Kobi a fait remarquer, il y a 5 ans, ayant un espace de premier plan dans les noms de classe ne causera aucun problème avec tous les navigateurs connus, donc la plus courte solution correcte serait en fait:
h.className += ' error';
Cela aurait dû être le réponse réelle problème réel .
Quoi qu'il en soit, les questions posées étaient ...
1) Pourquoi est-ce travail?
h.className += h.className ? ' error' : 'error'
L'opérateur conditionnel / ternaire fonctionne comme une instruction if, qui affecte le résultat de ses chemins de true
ou false
à une variable.
Alors que le code a fonctionné parce qu'il est évalué simplement:
if (h.className IS NOT null AND IS NOT undefined AND IS NOT '')
h.className += ' error'
else
h.className += 'error'
2) et pourquoi cette rupture?
h.className = h.className + h.className ? ' error' : 'error'
Les Etats question « qui donne un [n] erreur dans ma console », ce qui peut vous induire en erreur en pensant que le code ne fonctionne pas . En fait, le code suivant ne fonctionne, sans erreur , mais il retourne simplement « erreur » si la chaîne était pas vide et « erreur » si la chaîne était vide et ainsi ne répondaient pas aux exigences .
ce code entraîne toujours une chaîne qui ne contient que ' error'
ou 'error'
parce qu'il évalue à ce pseudo-code:
if ((h.className + h.className) IS NOT null AND IS NOT undefined AND IS NOT '')
h.className = ' error'
else
h.className = 'error'
La raison est que l'opérateur d'addition (+
au peuple commun) a « priorité » (6) supérieur à l'opérateur ternaire conditionnel / (15). Je sais les chiffres apparaissent en arrière
précédence signifie simplement que chaque type d'opérateur dans une langue est évaluée dans un ordre prédéfini particulier (et pas seulement de gauche à droite).
Référence: Javascript opérateur précédence
Comment faire pour modifier l'ordre d'évaluation:
Maintenant, nous savons pourquoi il échoue, vous devez savoir comment le faire fonctionner.
D'autres réponses parlent de changer la priorité , mais vous ne pouvez pas . Est précédence dur dans la langue. C'est juste un ensemble fixe de règles ... Cependant, vous pouvez modifier le ordre d'évaluation ...
L'outil dans notre boîte à outils qui peuvent modifier l'ordre d'évaluation est l'opérateur de regroupement (alias entre parenthèses). Elle le fait en assurant les expressions dans les parenthèses sont évaluées avant opérations en dehors des parenthèses. C'est tout ce qu'ils font, mais ça suffit.
Les crochets fonctionnent simplement parce qu'ils (les opérateurs de groupement) ont une priorité plus élevée que tous les autres opérateurs ( "il y a maintenant un niveau 0").
En ajoutant simplement entre parenthèses vous changer l'ordre d'évaluation pour assurer le test conditionnel est effectué en premier lieu, avant la concaténation de chaîne simple:
h.className = h.className + (h.className ? ' error' : 'error')
je quitte maintenant cette réponse à la rouille invisible parmi les autres:)
Je voudrais prendre explication de wayne:
<variable> = <expression> ? <true clause> : <false clause>
Lets considérer les deux cas:
case 1:
h.className += h.className ? 'true' : 'false'
- opérateur d'affectation fonctionne très bien et la valeur ajoutée se
- Lors de l'exécution pour la première fois, o / p: false
- 2ème fois. o / p: falsetrue - valeurs maintient annexant
affaire2: h.className = h.className + h.className? 'True': 'false'
- le résultat est identique cas 1
- Lors de l'exécution pour la première fois, o / p: false
- 2ème fois. o / p: faux - valeurs ne tiennent pas annexant
explanation
Dans le code ci-dessus, le cas 1 fonctionne très bien
alors que affaire2:
h.className = h.className + h.className ? 'true' : 'false'
is executed as
h.className = (h.className + h.className) ? 'true' : 'false'
h.className + h.className
=> considéré comme l'expression de l'opérateur ternaire comme opérateur ternaire est donné une priorité plus élevée. donc, toujours le résultat de l'expression ternaire est simplement attribué
Vous devez définir la priorité en utilisant des parenthèses
Vous devez définir l'ordre d'évaluation à considérer avec l'aide de crochets pour le cas 2 cas travailler 1
h.className = h.className + (h.className ? ' error' : 'error')