17.2 opérateurs : ordre de précédence |
See You Why? |
Dans la séquence prédente, nous avons fait allusion aux opérateurs logiques de JS. Dans le chapitre 12, nous avons fait allusion aux priorités relative des opérateurs mathématiques.
Cette séquence n'aura pas d'autres buts que de fixer la priorité des opérateurs logiques lorsqu'ils sont en présence d'opérateurs mathématiques. Nous les étudierons dans le même ordre que celui de la présentation de la séquence précédente, à savoir le ET, le OU puis le NOT.
Comme il reste des opérateurs dont nous n'avons pas encore tenu compte, nous analyserons la position de précédence des opérateurs de comparaison.
La logique booléenne parle de conjonction.
Commençons par comparer les priorités relatives du "ET logique" et de "l'affectation". En Belgique, on considère que l'on est en âge de travailler si l'on a plus de 18 ans et moins de 68 ans... désolé pour ceux qui ont subi une prolongation récente. On pourrait donc écrire :
age_travailler = (age >= 18) && (age <=65)
. Il s'agit bien d'affecter à la variable age_travailler une valeur booléenne qui doit être la conjonction de 2 conditions logiques.
En supposant que vous soyez en age légal de travailler, allez-vous
* d'abord affecter 'true' (puisque vous êtes supposé aux groupe en age de travailler) à la variable age_travailler,
puis traiter le ET LOGIQUE qui suit
ou
* d'abord vérifier la valeur logique de chacune des 2 conditions,
puis vérifier si elles sont toutes les deux vraies,
et enfin attribuer à la variable age_travailler la valeur de la conjonction des deux ?
Si vous avez choisi la première option, vous avez avantage à ne pas lire plus loin, mais à bien saisir la séquence précédente, ainsi que le chapitre 12.
Si c'est la seconde proposition qui vous agrée, vous avez probablement compris que les affectations ont des priorités bien plus faibles que la conjonction logique.
À la lecture de la séquence traitant de la priorité des opérateurs mathématiques, nous avions non seulement signalé que les affectations avaient une priorité faible, mais qu'il n'y avait qu'un seul opérateur qui avait une priorité encore plus faible.
Les affectations occupent la 17e place sur 18 si l'on prend en compte l'ordre de précédence. On peut donc conclure que l'indice de priorité de la conjonction logique est inférieur à 17.
Indice inférieur à 17, OK... mais supérieur à quoi... Essayons de comparer avec l'addition ou la soustraction qui ont même niveau de précédence, c-à-d 6.
Reprenons notre exemple de détermination de l'âge de travailler présenté ci-avant.
age_travailler = age-18 >= 0 && age-65 <=0
qui n'est rien d'autre qu'une écriture différente de la même condition.
JS va-t-il d'abord rechercher la valeur de la conjonction logique 0 && age
ou va-t-il d'abord effectuer les deux soustractions age-18
et age-65
, puis comparer les résultats à zéro, puis calculer la valeur de la conjonction des deux valeurs booléennes et enfin affecter cette valeur à la variable .
Si vous avez préféré la première suggestion, vous devriez relire la séquence précédente où nous avions noté que "Le ET logique, sert à tester la véracité de deux assertions logiques en même temps". Or, 0 et age ne sont pas des assertions logiques me semble-t-il...
Par contre, si c'est la seconde proposition qui vous agrée, vous avez probablement compris que les additions et/ou soustractions ont des priorités bien plus grandes que la conjonction logique.
Ce qui vous amènera à conclure que la conjonction logique se situe à un niveau oscillant entre 7 (6+1) et 16 (17-1).
La conjonction logique est en effet un opérateur qui se place au niveau 13.
Nous n'allons pas refaire toutes les opérations faites précédemment pour l'opérateur logique 'ET' et découvrir que lui aussi doit se situer à un niveau oscillant entre 7 et 16. Nous préférons situer la priorité de l'opérateur 'ET' par rapprt à celle de l'opérateur 'OU'.
J'ai eu l'occasion de lire à l'entrée d'un musée, les conditions d'entrée à mi-tarif : "Toute personne, non étudiant, de plus de 60 ans ne faisant pas partie de l'association des amis du musée, tout étudiant non membre de l'association, toute personne de moins de 60 ans et membre de l'association, toute personne de plus de 60 ans, ne faisant pas partie de l'association mais au chômage, tout étudiant de moins de 60 ans et non chômeur, toute personne membre de l'association au chômage, toute personne de plus de 60 ans, membre de l'association, non au chômage."
Je suppose que le lecteur aura compris qu'on ne peut pas avoir le profil de chaque personne en même temps et qu'il faudra répondre à l'un des critères, c'est-à-dire à l'un ou à l'autre. Les conditions d'entrée à mi-tarif seront une disjonction de cas et deviendront donc :
* Toute personne, non étudiant, de plus de 60 ans ne faisant pas partie de l'association des amis du musée
* tout étudiant non membre de l'association
* toute personne de moins de 60 ans et membre de l'association
* toute personne de plus de 60 ans, ne faisant pas partie de l'association mais au chômage,
* tout étudiant de moins de 60 ans et non chômeur,
* toute personne membre de l'association au chômage,
* toute personne de plus de 60 ans, membre de l'association, non au chômage.
Pour avoir droit à l'entrée à prix réduit, il faut appartenir à l'un des 7 cas envisagés (le 1er ou le 2e ou le 3e...),
mais les conditions pour chaque cas sont multiples et doivent toutes être satisfaites conjointement (la 1re et la 2e et la 3e...),
chaque cas est une conjonction de conditions.
Comment savoir si j'ai droit à la réduction ?
Je dois d'abord relever la valeur logique de chaque condition éléméntaire,
puis verifier si j'appartiens à l'un des cas, donc effectuer la conjonction des conditions pour chaque cas,
puis vérifier si l'un des cas me correspond en effectuant une disjonction des cas... en espérant que l'un d'eux soit le bon.
On pourrait formaliser ce cas ainsi :
cas1 OR cas2 OR cas3 OR cas4 OR cas5 OR cas6 OR cas7,
et, en convenant d'appeler ainsi chaque proposition élémentaire :
e, pour "être étudiant" ;
a, pour "être agé" ;
m, pour "être membre de l'association" ;
c, pour "être au chomage" ;
on écrirait alors
!e&a&!m OR e&!m OR !a&m OR a&!m&c OR e&!a&!c OR m&c OR a&m&!c
Bref, il serait possible de réduire cette règlementation, mais ce n'est pas notre but ici. Il s'agissait de découvrir que les conjonctions ont une priorité supérieure aux disjonctions. En d'autres mots, qu'on effectue les 'OU' après les 'ET'.
Si la disjonction a une priorité plus faible que la conjonction, c'est qu'elle aura un indice plus grand.
En effet, la disjonction logique est en effet un opérateur qui se place au niveau 14.
Nous n'allons pas refaire toutes les opérations faites précédemment pour les opérateurs logiques 'ET' et 'OU'. Nous ferons remarquer cependant que les opérateurs de conjonction et de disjonction sont des opérateurs qui impliquent chaque fois deux opérandes. La négation n'en compte qu'un seul, c'est un opérateur unaire, comme l'étaient les opérateurs d'incrémentation et décrémentation.
Or, déjà dans notre chapitre 12, nous avions observé que les opérateurs unaires ont souvent une priorité assez élevée (niveau 3 pour l'incrémentation, décrémentation; niveau 4 pour + et - unaires). Le NOT logique, lui aussi, bénéficie d'une priorité plus grande car on l'applique immédiatement sur l'opérande qui le suit... sans oublier de tenir compte des parenthèses qui peuvent venir bouleverser cet ordre. Le NOT logique se place au niveau 4.
Les conditions sont le plus souvent des comparaisons (==, <, <=, !=, >, >=, etc.).
Comme promis, il nous restera à voir la position de précédence des opérateurs d'égalité et de comparaison. Nous commencerons par les opérateurs d'égalité pour voir ensuite les opérateurs de comparaison.
Nous désignerons sous cette appellation les opérateurs ==, !=, === et !== qui déterminent si deux objets sont identiques ou pas.
Les opérateurs == et === sont des opérateurs d'égalité. Le premier sert à vérifier si les deux opérandes sont égaux ; le second s'ils sont strictement égaux. Mais alors, "est égal à" et "est strictement égal à" ne sont pas des expressions égales ? Non, JS est très souple quant au typage de ses variables (voir déjà chap. 4) et JS fait une distinction entre les égalités strictes et les égalités simples.
Par l'opérateur ==, JS considère qu'il y a égalité après une éventuelle conversion de types.
Par l'opérateur ===, JS considère qu'il y a stricte égalité sans conversion de types.
Si les deux opérandes ne sont pas du même type,
JavaScript convertit les opérandes (quand c'est possible), puis seulement elle applique en fait la comparaison. Ainsi, si JS doit comparer 5 et "5", beaucoup de langages diraient qu'il ne peut y avoir égalité entre une valeur numérique et une valeur de type chaine de caractères... Cependant, pour JS,
5 == "5" aura la valeur 'true',
5 === "5" aura la valeur 'false'.
Par l'opérateur !=, JS considère qu'il n' y a pas égalité même après une éventuelle conversion de types.
Par l'opérateur !==, JS considère qu'il n'y a pas stricte égalité ou que les opérandes sont de type différent.
Si l'un des opérandes est un nombre ou un booléen,
les opérandes sont convertis en valeurs numériques (vrai = true = 1 et faux = false = 0), si possible,
d'autre part, si l'un des opérandes est une chaîne,
l'autre opérande est converti en une chaîne si possible.
Si les deux opérandes sont des objets,
alors JavaScript compare références internes qui sont égaux quand opérandes se réfèrent au même objet en mémoire.
Et, comme notre propos est de déterminer l'ordre de précédence des opérateurs, JS place la priorité de tous ces opérateurs d'égalité au niveau 9, ce qui les rend prioritaires par rapport à la conjonction logique ET (de niveau 13), mais moins prioritaire que l'addition + (de niveau 6).
JS effectuera d'abord l'addition, puis vérifiera les égalités et enfin fera le conjonction logique des deux opérandes qui restent... s'il n'y a pas de parenthèses pour bouleverser cet ordre.
Cela signifie que si l'on écrit :
condition = age == 10 + 8 && nationalite == "DZ"
, la valeur que prendra le variable logique condition sera déterminée ainsi :
age | == | 10 | + 8 | && | nationalite | == "DZ" |
age | == | 18 | && | nationalite | == "DZ" | |
true | && | false | ||||
false |
si vous avez 18 ans (mais pas plus) et que vous êtes de nationalité marocaine (et non algérienne)... condition prendrait la valeur false.
Pour beaucoup, les opérateurs d'égalité sont des opérateurs de comparaison. Pour certains aussi, les opérateurs de comparaison sont appelés opérateurs relationnels. Nous ne contredirons pas ces approches.
Nous ne ferons pas l'affront à nos lecteurs d'expliquer la différence entre "est strictement plus petit", "est plus petit ou égal", "est strictement plus grand" et "est plus grand ou égal". Nous voulons cependant attirer l'attention du lecteur sur la non existence de l'opérateur '<>' qui existe dans plusieurs langages informatiques, JS ne connait que l'opérateur '!=' pour exprimer "est différent de".
JS place ces 4 opérateurs à un même niveau de priorité, à peine plus élevé que les opérateurs d'égalité vus ci-avant. Il les situe au niveau 9.
La séquence suivante n'est rien d'autre qu'un tableau plus complet des différents opérateurs classés par ordre de précédence (de la plus grande priorité [1] à la plus faible priorité [18])
voir suite >>>
voir suite >>>
voir suite >>>
voir suite >>>