Opérateur priorité avec Javascript opérateur ternaire

Je n'arrive pas à enrouler 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 la suivante:

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

Mais ce n'est pas correct, car cela donne une erreur dans ma console.

alors ma question Est Comment dois-je interpréter ce code correctement?

115
demandé sur Boaz 2009-11-24 12:27:01

7 réponses

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

vous voulez que l'opérateur travaille pour h.className , mieux vaut être précis à ce sujet.

Bien sûr, aucun mal ne devrait venir de h.className += ' error' , mais c'est une autre question.

en outre, notez que + a priorité sur l'opérateur ternaire: priorité de L'opérateur JavaScript

140
répondu Kobi 2012-10-10 04:25:23

Pensez-y de cette façon:

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

la façon dont la déclaration est exécutée est essentiellement comme suit:

  1. Ne <expression> true ou false?
  2. si <expression> est évalué à true, alors la valeur de <true clause> est assignée à <variable> , <false clause> est ignorée, et la déclaration suivante est exécutée.
  3. si <expression> évalue à false, puis <true clause> est ignoré et la valeur de <false clause> est attribuée à <variable> .

la chose importante à réaliser avec l'opérateur ternaire dans cette langue et d'autres est que quel que soit le code dans <expression> devrait produire un résultat booléen une fois évalué: soit vrai ou faux.

dans le cas de votre exemple, remplacer "attribué à" dans mon explication par "ajouté à", ou similaire pour n'importe quelle arithmétique vous êtes en utilisant, le cas échéant.

129
répondu Wayne Koorts 2013-03-16 03:47:57

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, ce qui serait si elle était indéterminée. Si c'est vrai (c.-à-d. si un nom de classe est déjà spécifié), alors l'erreur est ajoutée avec un espace (c.-à-d. en ajoutant une classe nouvelle ), sinon il est ajouté sans l'espace.

le code peut être réécrit comme vous le suggérez, mais vous devez spécifier que h.className doit être utilisé pour la comparaison de la véracité, plutôt que pour l'utilisation de sa valeur réelle, dans l'opérateur ternaire, donc assurez-vous que vous ne vous embêtez pas avec la concaténation des valeurs en même temps que faire votre opération ternaire:

h.className = h.className + (h.className ? ' error' : 'error');
10
répondu David Hedlund 2009-11-24 09:34:44

le côté droit de l'opérateur = est évalué de gauche à droite. Donc,

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';

il faut séparer le ternaire énoncé entre parenthèses

h.className = h.className + (h.className ? ' error' : 'error');
4
répondu Justin Johnson 2009-11-24 09:36:23
if (h.className) {
    h.className = h.className + ' error';
} else {
    h.className = h.className + 'error';
}

doit être l'équivalent de:

h.className += h.className ? ' error' : 'error';
3
répondu Darin Dimitrov 2009-11-24 09:34:58

je sais que c'est une question très ancienne, mais je ne suis pas 100% satisfait de l'une des réponses car elles semblent toutes incomplètes. Nous voici donc de nouveau de premiers principes:

l'objectif général de l'utilisateur:

résume le code: "je souhaite ajouter un nom de classe error à une chaîne, éventuellement avec un espace principal s'il y a déjà des noms de classe dans la chaîne."

solution la plus simple

comme Kobi l'a souligné, il ya 5 ans, ayant un espace de tête dans les noms de classe ne sera pas causer de problèmes avec les navigateurs connus, de sorte que la solution correcte la plus courte serait en fait:

h.className += ' error';

Qui aurait été le la réponse à la problème .


quoi qu'il en soit, les questions posées étaient...

1) Pourquoi cela a-t-il fonctionné?

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

l'opérateur conditionnel/ternaire fonctionne comme une instruction if, qui assigne le résultat de ses chemins true ou false à une variable.

de sorte que le code a fonctionné parce qu'il est évalué simplement comme:

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'

la question dit "qui donne une erreur dans ma console", qui peut induire en erreur vous pensez que le code ne fonctionne pas . En fait, le code suivant fonctionne, sans erreur , mais il renvoie "erreur" si la chaîne de caractères n'était pas "1519180920 vide" et "erreur" si la chaîne de caractères était vide et donc ne répond pas aux exigences .

ce code donne 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 en est que l'opérateur d'addition ( + au folk commun) a plus de" priorité " (6) que l'opérateur conditionnel/ternaire (15). je sais que les chiffres apparaissent à l'envers

priorité signifie simplement que chaque type d'opérateur dans une langue est évalué dans un ordre prédéfini particulier (et pas seulement de gauche à droite).

Référence: Opérateur Javascript Priorité

Comment changer l'ordre d'évaluation:

maintenant que 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 . La préséance est liée à la langue. C'est juste un ensemble fixe de règles... Toutefois, vous pouvez modifier le ordre d'évaluation ...

l'outil dans notre boîte à outils qui peut changer l'ordre d'évaluation est l'opérateur de groupement (aka parenthèses). Il le fait en s'assurant que 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 opérateurs) ont priorité plus élevée que tous les autres opérateurs ("Il ya maintenant un niveau 0").

en ajoutant simplement des crochets vous modifiez l'ordre d'évaluation pour s'assurer que le test conditionnel est effectué en premier, avant la simple chaîne concaténation:

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

je vais maintenant laisser cette réponse rouiller invisible parmi les autres:)

1
répondu Gone Coding 2014-06-11 17:19:17

j'aimerais choisir l'explication de wayne:

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

permet de considérer les deux cas:

case 1:
h.className += h.className ? 'true' : 'false'     
  • opérateur d'affectation fonctionne très bien et la valeur est ajoutée
  • lorsque pour la première fois, o/p: false,
  • 2e fois. o/p: falsetrue -- valeurs maintient en ajoutant

case2: h.className = h.className + h.className ? 'true' : 'false'

  • le résultat n'est pas le même que dans le cas 1
  • lorsque pour la première fois, o/p: false,
  • 2e fois. o/p: faux-valeurs ne tiennent pas en ajoutant

explanation

dans le code ci-dessus, l'affaire 1 fonctionne amende

attendu que case2:

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 en tant qu'opérateur ternaire a priorité plus élevée. donc, toujours le résultat de l'expression ternaire est assigné

vous devez définir la priorité en utilisant les parenthèses

Vous devez définir l'ordre d'évaluation à considérer avec l'aide de crochets pour le cas 2 cas 1

h.className = h.className + (h.className ? ' error' : 'error') 
1
répondu Angelin Nadar 2014-06-12 11:03:12