Expressions et opérateurs
Dans ce chapitre, nous décrirons les expressions et opérateurs en JavaScript, qui permettent notamment l'affectation, la comparaison, les opérations arithmétiques, binaires, logiques, la manipulation de chaîne de caractères, etc.
Uneexpression peut être vue comme une unité de code valide qui est résolue en une valeur. Il existe deux types d'expressions, celles qui ont des effets de bord (par exemple l'affectation d'une valeur) et celles qui sont purement évaluées.
L'expressionx = 7
fait partie de la première catégorie. Elle utilisel'opérateur=
afin d'affecter la valeur sept à la variablex
. L'expression elle-même est évaluée avec la valeur7
.
L'expression3 + 4
fait partie de la deuxième catégorie. Elle utilise l'opérateur+
afin d'ajouter3
et4
pour produire une valeur :7
. Toutefois, si cette valeur n'est pas utilisée au sein d'une structure plus importante (par exemple avecune déclaration de variable commeconst z = 3 + 4
), elle sera immédiatement écartée (il s'agit généralement dans ce cas d'une erreur de programmation, car l'évaluation ne produira aucun effet).
Comme les exemples précédents ont permis de montrer, toutes les expressions complexes sont formées avec desopérateurs, tels que=
ou+
. Dans cette section, nous verrons les opérateurs suivants :
- Opérateurs d'affectation
- Opérateurs de comparaison
- Opérateurs arithmétiques
- Opérateurs binaires
- Opérateurs logiques
- Opérateurs pour les grands entiers
- Opérateurs pour les chaînes de caractères
- Opérateur conditionnel (ternaire)
- Opérateur virgule
- Opérateurs unaires
- Opérateurs relationnels
Ces opérateurs assemblent des opérandes formés par des opérateurs de précédence plus haute ou par une desexpressions de base. Une liste complète et détaillée des opérateurs et expressions est également disponible dansla référence.
Laprécédence des opérateurs détermine l'ordre selon lequel ils sont appliqués pour l'évaluation d'une expression. Par exemple :
const x = 1 + 2 * 3;const y = 2 * 3 + 1;
Bien que*
et+
soit placés dans un ordre différent, ces deux expressions produisent la valeur7
, car*
a une précédence qui l'emporte sur celle de+
. L'expression formée par les deux opérandes entourant*
est donc toujours évaluée en premier ici. Vous pouvez passer outre la précédence des opérateurs en utilisant les parenthèses (ce qui créeune expression groupée, qui est une expression de base). Pour un tableau complet détaillant la précédence des opérateurs et les éventuels pièges, voirla page de référence sur la précédence des opérateurs.
JavaScript possède des opérateursbinaires etunaires, ainsi qu'un opérateur ternaire spécial (l'opérateur conditionnel).Un opérateur binaire a besoin de deux opérandes, un placé avant l'opérateur (à sa gauche) et un placé après l'opérateur (à sa droite) :
opérande1 opérateur opérande2
3 + 4
etx * y
sont deux exemples d'expression qui utilisent un opérateur binaire. Sous cette forme, on parle d'opérateur binaireinfixe, car l'opérateur est placé entre les deux opérandes. Tous les opérateurs binaires de JavaScript sont infixes.
Un opérateur unaire fonctionne avec un seul opérande, situé avant ou après l'opérateur :
opérateur opérandeopérande opérateur
x++
et++x
sont deux exemples d'expression avec un opérateur unaire. La formeopérateur opérande
fonctionne pour les opérateurs unairespostfixes, tandis que la formeopérande opérateur
fonctionne pour les opérateurs unairespréfixes.++
et--
sont les deux seuls opérateurs postfixes de JavaScript. Tous les autres opérateurs unaires, comme!
outypeof
, sont préfixes.
Opérateurs d'affectation
Un opérateur d'affectation affecte une valeur à son opérande gauche selon la valeur de son opérande droit. L'opérateur d'affectation simple est le signe égal (=
), qui affecte la valeur de son opérande droit à son opérande gauche. Autrement dit,x = f()
est une expression d'affectation qui affecte la valeur def()
àx
.
Il existe également des opérateurs d'affectation composites qui sont des raccourcis pour les opérations listées dans le tableau qui suit :
Nom | Opérateur | Signification |
---|---|---|
Affectation | x = f() | x = f() |
Affectation après addition | x += f() | x = x + f() |
Affectation après soustraction | x -= f() | x = x - f() |
Affectation après multiplication | x *= f() | x = x * f() |
Affectation après division | x /= f() | x = x / f() |
Affectation du reste | x %= f() | x = x % f() |
Affectation après exponentiation | x **= f() | x = x ** f() |
Affectation après décalage à gauche | x <<= f() | x = x << f() |
Affectation après décalage à droite | x >>= f() | x = x >> f() |
Affectation après décalage à droite non signé | x >>>= f() | x = x >>> f() |
Affectation après ET binaire | x &= f() | x = x & f() |
Affectation après OU exclusif binaire | x ^= f() | x = x ^ f() |
Affectation après OU binaire | x |= f() | x = x | f() |
Affectation après ET logique | x &&= f() | x && (x = f()) |
Affectation après OU logique | x ||= f() | x || (x = f()) |
Affectation après coalescence des nuls | x ??= f() | x ?? (x = f()) |
Affectation aux propriétés
Si une expression est évaluée enun objet, le côté gauche d'une expression d'affectation pourra être utilisé pour des affectations sur les propriétés de cette expression. Par exemple :
const obj = {};obj.x = 3;console.log(obj.x); // Affiche 3.console.log(obj); // Affiche { x: 3 }.const key = "y";obj[key] = 5;console.log(obj[key]); // Affiche 5.console.log(obj); // Affiche { x: 3, y: 5 }.
Pour plus d'informations sur les objets, voirUtiliser les objets.
Si une expression n'est pas évaluée en un objet, les affectations aux propriétés de cette expression ne fonctionneront pas :
const val = 0;val.x = 3;console.log(val.x); // Affiche undefined.console.log(val); // Affiche 0.
Enmode strict, le fragment de code qui précède déclenchera une exception, car on ne peut pas affecter de propriétés à des valeurs primitives.
C'est une erreur que d'affecter des valeurs à des propriétés non-modifiables ou à des propriétés d'une expression sans propriété (null
ouundefined
).
Décomposition
Pour les affectations plus complexes,l'affectation par décomposition permet de construire une expression JavaScript pour extraire des données de tableaux ou d'objets avec une syntaxe qui reflète les littéraux utilisés pour la construction de tableaux ou d'objets.
const toto = ["un", "deux", "trois"];// sans décompositionconst un = toto[0];const deux = toto[1];const trois = toto[2];// avec décompositionconst [un, deux, trois] = toto;
Évaluation et imbrication
En général, les affectations sont utilisées pour une déclaration de variable (c'est-à-dire avec les instructionsconst
,let
, ouvar
) ou comme instructions indépendantes.
// Déclare une variable x et l'initialise avec le résultat de f().// Le résultat de l'expression d'affectation "x = f()" est écarté.let x = f();x = g(); // Réaffecte le résultat de g() à la variable x.
Toutefois, à l'instar des autres expressions, les expressions d'affectation commex = f()
ont comme résultat une valeur. Bien que cette valeur ne soit généralement pas utilisée, elle peut être utilisée dans une autre expression.
L'enchaînement d'affectations ou l'imbrication d'affectation dans d'autres expressions peut produire des résultats étranges. C'est pour cette raison que certains guides stylistiques JavaScriptdéconseillent l'enchaînement ou l'imbrication d'affectations). Toutefois, vous pourrez en voir dans certains codes et il est donc important de comprendre comment ils fonctionnent.
En enchaînant ou en imbriquant les expressions d'affectation, le résultat de chaque expression peut être affecté à une autre variable. On peut s'en servir pour journaliser, la placer dans un tableau, un appel de fonction, etc.
let x;const y = (x = f()); // Une notation équivalente serait : const y = x = f();console.log(y); // Affiche la valeur de retour de l'affectation x = f().console.log((x = f())); // Affiche la valeur de retour directement.// Une expression d'affectation peut être imbriquée à n'importe quel// endroit où les expressions sont autorisées, que ce soit comme// élément d'un littéral de tableau ou comme argument dans un appel// de fonctionconsole.log([0, (x = f()), 0]);console.log(f(0, (x = f()), 0));
Le résultat de l'évaluation correspond à l'expression à droite du signe=
dans la colonne « Signification » du tableau ci-avant. Cela signifie que l'évaluation dex = f()
aura comme résultat celui def()
, que l'évaluation dex += f()
aura comme résultat la sommex + f()
, que celle dex **= f()
aura comme résultatx ** f()
, etc.
Pour les affectations logiques,x &&= f()
,x ||= f()
, etx ??= f()
, la valeur de retour est celle de l'opération logique sans affectation, soitx && f()
,x || f()
, etx ?? f()
, respectivement.
Lorsqu'on enchaîne ces expressions sans parenthèses ou opérateur de groupement comme les littéraux de tableau, les expressions d'affectation sontgroupées de droite à gauche (elles sontassociatives à droite), mais sontévaluées de gauche à droite.
On notera que pour les opérateurs d'affectation, à l'exception de=
, les valeurs résultantes sont toujours basées sur les valeurs des opérandesavant l'opération.
Par exemple, si on a les fonctionsf
etg
et les variablesx
ety
comme suit :
function f() { console.log("F!"); return 2;}function g() { console.log("G!"); return 3;}let x, y;
Prenons ces trois exemples :
y = x = f();y = [f(), (x = g())];x[f()] = g();
Exemple d'évaluation n°1
y = x = f()
est équivalente ày = (x = f())
, car l'opérateur d'affectation est associatif à droite. Toutefois l'évaluation se fait de gauche à droite :
- L'évaluation de l'expression d'affectation
y = x = f()
commence.- L'opérande
y
à gauche de l'affectation est évalué comme une référence à la variable nomméey
. - L'évaluation de l'expression d'affectation
x = f()
commence.- L'opérande
x
à gauche de l'affectation est évalué comme une référence à la variable nomméex
. - L'appel de fonction
f()
affiche "F!" dans la console et renvoie la valeur2
. - Ce résultat de
f()
,2
, est affecté àx
.
- L'opérande
- L'évaluation de l'expression d'affectation
x = f()
est maintenant terminée. Son résultat est la nouvelle valeur dex
, qui est2
. - Ce résultat,
2
, est à son tour affecté ày
.
- L'opérande
- L'évaluation de l'expression d'affectation
y = x = f()
est maintenant terminée. Son résultat est la nouvelle valeur dey
, qui est ici2
. La valeur2
a été affectée àx
ety
, et la console a affiché "F!".
Exemple d'évaluation n°2
y = [ f(), x = g() ]
est également évaluée de gauche à droite :
- L'évaluation de l'expression d'affectation
y = [ f(), x = g() ]
commence.- L'opérande
y
à gauche de l'affectation est évalué comme une référence à la variable nomméey
. - L'évaluation du littéral de tableau
[ f(), x = g() ]
commence.- L'appel de fonction
f()
affiche "F!" dans la console et renvoie la valeur2
. - L'évaluation de l'expression d'affectation
x = g()
commence.- L'opérande
x
à gauche de l'affectation est évalué comme une référence à la variable nomméex
. - L'appel de fonction
g()
affiche "G!" dans la console et renvoie la valeur3
. - Ce résultat de
g()
,3
, est affecté àx
.
- L'opérande
- L'évaluation de l'expression d'affectation
x = g()
est maintenant terminée. Son résultat est la nouvelle valeur dex
3
. Ce résultat devient l'élément qui suit dans le littéral de tableau (après le2
provenant def()
).
- L'appel de fonction
- L'évaluation du littéral de tableau
[ f(), x = g() ]
est maintenant terminée. Son résultat est un tableau avec deux valeurs :[ 2, 3 ]
. - Ce tableau,
[ 2, 3 ]
, est affecté ày
.
- L'opérande
- L'évaluation de l'expression d'affectation
y = [ f(), x = g() ]
est maintenant terminée. Son résultat est la nouvelle valeur dey
, qui est[ 2, 3 ]
.3
est affecté àx
,[ 2, 3 ]
est affecté ày
et la console a affiché "F!" puis "G!".
Exemple d'évaluation n°3
x[f()] = g()
est également évaluée de gauche à droite. Dans cet exemple, on part du principe que la valeur dex
est déjà un objet (pour plus d'informations sur les objets, voirUtiliser les objets).
- L'évaluation de l'expression d'affectation
x[f()] = g()
commence.- L'évaluation de l'accès à la propriété
x[f()]
situé à gauche de l'opérateur d'affectation commence.- Le
x
est évalué comme une référence à la variable nomméex
. - Ensuite, l'appel
f()
affiche "F!" dans la console et renvoie la valeur2
.
- Le
- L'évaluation de
x[f()]
est maintenant terminée et son résultat est une variable qui référence la propriétéx[2]
. - Ensuite, l'appel à la fonction
g()
affiche "G!" dans la console et renvoie la valeur3
. - Ce résultat,
3
, est affecté àx[2]
(cette étape réussira uniquement si la valeur dex
est unobjet)?
- L'évaluation de l'accès à la propriété
- L'évaluation de l'expression d'affectation
x[f()] = g()
est maintenant terminée. Son résultat est la nouvelle valeur dex[2]
, qui est3
.3
a été affecté àx[2]
et la console a affiché "F!" puis "G!".
Éviter les enchaînements d'affectation
L'enchaînement ou l'imbrication d'affectations dans d'autres expressions peut produire d'étranges résultats et c'est pour cette raisonque les enchaînements et imbrications d'affectation sont déconseillés).
On évitera en particulier les enchaînements d'affectation dans une instructionconst
,let
, ouvar
quine fonctionnent pas dans la plupart des cas. Seule la variable la plus à gauche sera alors déclarée et les variables intermédiaires dans la chaîne ne serontpas déclarées par l'instructionconst
/let
/var
. Ainsi, si on a :
const z = y = x = f();
On pourrait penser que cela permet de déclarer les variablesx
,y
, etz
. Cependant, seule la variablez
est déclarée.y
etx
sont des références invalides à des variables inexistantes (enmode strict) ou, pire, créent desvariables globales pourx
ety
enmode non-strict.
Opérateurs de comparaison
Un opérateur de comparaison compare ses opérandes et renvoie une valeur logique selon que la comparaison est vraie ou non. Les opérandes peuvent être des nombres, des chaînes de caractères, des booléens ou desobjets. Les chaînes de caractères sont comparées selon l'ordre lexicographique standard en utilisant les valeurs Unicode.
Dans la plupart des cas, si les deux opérandes ne sont pas du même type, le moteur JavaScript tentera de les convertir dans un type approprié pour la comparaison. Cela entraîne généralement une comparaison numérique des opérandes.
Les opérateurs===
et!==
sont des exceptions à cette règle de conversion : ils réalisent des comparaisons d'égalité et d'inégalité strictes. Ces opérateurs n'effectuent pas de conversion des opérandes avant la vérification de l'égalité.Le tableau qui suit décrit les opérateurs de comparaison en utilisant ce fragment de code comme exemple :
const var1 = 3;const var2 = 4;
Opérateur | Description | Exemples qui renvoienttrue |
---|---|---|
Égalité (== ) | Renvoietrue si les opérandes sont égaux (après conversion implicite). | 3 == var1 "3" == var1 3 == '3' |
Inégalité (!= ) | Renvoietrue si les opérandes sont différents (après conversion implicite). | var1 != 4 var2 != "3" |
Égalité stricte (=== ) | Renvoietrue si les opérandes sont égaux et du même type. Voir égalementObject.is() etl'égalité en JavaScript. | 3 === var1 |
Inégalité stricte (!== ) | Renvoietrue si les opérandes sont du même type et différents ou s'ils ne sont pas du même type. | var1 !== "3" 3 !== '3' |
Supériorité stricte (> ) | Renvoietrue si l'opérande gauche est strictement supérieur à l'opérande droit. | var2 > var1 "12" > 2 |
Supériorité (>= ) | Renvoietrue si l'opérande gauche est supérieur ou égal à l'opérande droit. | var2 >= var1 var1 >= 3 |
Infériorité stricte (< ) | Renvoietrue si l'opérande gauche est strictement inférieur à l'opérande droit. | var1 < var2 "2" < 12 |
Infériorité (<= ) | Renvoietrue si l'opérande gauche est inférieur ou égal à l'opérande droit. | var1 <= var2 var2 <= 5 |
Note :=>
n'est pas un opérateur de comparaison, il s'agit de la notation pourles fonctions fléchées.
Opérateurs arithmétiques
Un opérateur arithmétique combine des opérandes numériques et renvoie une valeur numérique. Les opérateurs arithmétiques standard sont l'addition (+
), la soustraction (-
), la multiplication (*
), et la division (/
). Ces opérateurs fonctionnent comme dans la plupart des langages de programmation qui utilisent les nombres flottants (la division par zéro donne notammentInfinity
). On pourra par exemple avoir :
1 / 2; // 0.51 / 2 === 1.0 / 2.0; // true
En plus des opérations arithmétiques standard (+
,-
,*
,/
), JavaScript fournit les opérateurs arithmétiques suivants :
Opérateur | Description | Exemple |
---|---|---|
Reste (% ) | Un opérateur binaire qui renvoie le reste entier de la division des deux opérandes. | `12 % 5` renvoie `2`. |
Incrément (++ ) | Un opérateur unaire qui ajoute un à son opérande. S'il est utilisé en opérateur préfixe (++x ), il renvoie la valeur de son opérande après y avoir ajouté un. S'il est utilisé en opérateur postfixe (x++ ), il renvoie la valeur de l'opérande avant l'ajout de un. | Six vaut 3, alors++x définitx avec 4 et renvoie 4, tandis quex++ renvoie 3 puis, uniquement après, définitx avec 4. |
Décrément (-- ) | Un opérateur unaire qui soustrait un à son opérande. La valeur de retour est analogue à celle de l'opérateur d'incrément. | Six vaut 3, alors--x définitx avec 2 et renvoie 2, tandis quex-- renvoie 3 puis, uniquement après, définitx avec 2. |
Négation unaire (- ) | Un opérateur unaire qui renvoie l'opposé de l'opérande. | Six vaut 3,-x renvoie -3. |
Plus unaire (+ ) | Un opérateur unaire qui tente la conversion de l'opérande en nombre si ce n'est pas déjà une valeur numérique. |
|
Opérateur d'exponentiation (** ) | Élève une base donnée par l'opérande gauche à la puissance donnée par l'opérande droit. | 2 ** 3 renvoie8 .10 ** -1 renvoie0.1 . |
Opérateurs binaires
Un opérateur binaire traite les opérandes comme des suites de 32 bits (des zéros ou des uns) plutôt que comme des nombres décimaux, hexadécimaux et octaux. Ainsi, le nombre décimal 9 se représente en binaire comme 1001. Les opérateurs binaires effectuent leur opération sur des représentations binaires et renvoient des valeurs numériques.
Le tableau qui suit détaille les opérateurs binaires JavaScript.
Opérateur | Utilisation | Description |
---|---|---|
ET binaire | a & b | Renvoie un à chaque position pour laquelle les bits des deux opérandes valent un. |
OU binaire | a | b | Renvoie un zéro à chaque position pour laquelle les bits des deux opérandes valent zéro. |
OU exclusif binaire | a ^ b | Renvoie un zéro à chaque position pour laquelle les bits sont les mêmes. [Renvoie un à chaque position où les bits sont différents.] |
NON binaire | ~ a | Inverse les bits de l'opérande. |
Décalage à gauche | a << b | Décale la représentation binaire dea deb bits vers la gauche, en ajoutant des zéros à droite. |
Décalage à droite avec propagation du signe | a >> b | Décale la représentation binaire dea deb bits vers la droite, enlevant les bits en trop. |
Décalage à droite avec remplissage à zéro | a >>> b | Décale la représentation binaire dea deb bits vers la droite, enlevant les bits en trop et en ajoutant des zéros à gauche. |
Opérateurs binaires logiques
Les opérateurs logiques binaires fonctionnent de la façon suivante :
Les opérandes sont convertis en entiers sur 32 bits. Pour les nombres dont la valeur binaire dépasse 32 bits, les bits les plus hauts sont abandonnés. Ainsi, l'entier suivant sur plus de 32 bits sera converti en entier sur 32 bits :
Avant : 1110 0110 1111 1010 0000 0000 0000 0110 0000 0000 0001Après : 1010 0000 0000 0000 0110 0000 0000 0001
Chaque bit du premier opérande est associé au bit correspondant du second opérande : le premier bit avec le premier bit, le second avec le second et ainsi de suite.
L'opérateur est appliqué sur chaque paire ainsi constituée et le résultat est construit en binaire.
Par exemple, la représentation binaire du nombre décimal9
est1001
, et celle du nombre décimal15
est1111
. Aussi, quand on utilise les opérateurs binaires sur ces valeurs, on a les résultats suivants :
Expression | Résultat | Description binaire |
---|---|---|
15 & 9 | 9 | 1111 & 1001 = 1001 |
15 | 9 | 15 | 1111 | 1001 = 1111 |
15 ^ 9 | 6 | 1111 ^ 1001 = 0110 |
~15 | -16 | ~ 0000 0000 … 0000 1111 = 1111 1111 … 1111 0000 |
~9 | -10 | ~ 0000 0000 … 0000 1001 = 1111 1111 … 1111 0110 |
On notera que tous les 32 bits sont inversés lors de l'utilisation de l'opérateur NON binaire et que les valeurs avec le bit le plus à gauche à 1 représentent des valeurs négatives (représentation en complément à deux). Aussi, l'évaluation de~x
fournira la même valeur que-x - 1
.
Opérateurs de décalage binaire
Les opérateurs de décalage binaire utilisent deux opérandes : celui de gauche est la quantité sur laquelle effectuer le décalage et celui de droite indique le nombre de bits à décaler. La direction de l'opération de décalage dépend de l'opérateur utilisé.
Les opérateurs de décalage convertissent leurs opérandes en entiers sur 32 bits et renvoient un résultat de typeNumber
ouBigInt
selon la règle suivante : si l'opérande gauche est de typeBigInt
, la valeur de retour sera de typeBigInt
et sinon, la valeur de retour sera de typeNumber
.
Les opérateurs de décalage sont listés dans le tableau suivant.
Opérateur | Description | Exemple |
---|---|---|
Décalage à gauche (<< ) | Cet opérateur décale la valeur du premier opérande du nombre de bits indiqué vers la gauche. Les bits en trop sont abandonnés et des bits à 0 sont ajoutés sur la droite. | 9<<2 donne36 , car1001 , décalé de 2 bits à gauche vaut100100 en binaire, ce qui correspond à36 en décimal. |
Décalage à droite avec propagation du signe (>> ) | Cet opérateur décale la valeur du premier opérande du nombre de bits indiqué vers la droite. Les bits en trop à droite sont abandonnés. Des copies du bit le plus à gauche sont ajoutés sur la gauche. | 9>>2 donne2 , car1001 décalé de 2 bits à droite vaut10 en binaire, ce qui correspond à2 en décimal. De même,-9>>2 donne-3 , car le signe est conservé. |
Décalage à droite avec remplissage à zéro (>>> ) | Cet opérateur décale la valeur du premier opérande du nombre de bits indiqué vers la droite. Les bits en trop à droite sont abandonnés. Des bits à zéro sont ajoutés sur la gauche. | 19>>>2 donne4 , car10011 décalé de deux bits à droite devient100 en binaire, ce qui vaut4 en décimal. Pour les valeurs positives, le décalage à droite avec remplissage à zéro et le décalage à droite avec propagation du signe fourniront le même résultat. |
Opérateurs logiques
Les opérateurs logiques sont généralement utilisés avec des valeurs booléennes. Lorsque c'est le cas, la valeur de retour est également booléenne. Plus généralement, les opérateurs&&
et||
renvoient la valeur d'un des deux opérandes (et peuvent donc renvoyer une valeur qui n'est pas un booléen). Ces opérateurs sont décrits dans le tableau suivant.
Opérateur | Utilisation | Description |
---|---|---|
ET logique (&& ) | expr1 && expr2 | Renvoieexpr1 si elle peut être convertie enfalse et renvoieexpr2 sinon. Lorsqu'il est utilisé avec des valeurs booléennes,&& renvoietrue si les deux opérandes valenttrue etfalse sinon. |
OU logique (|| ) | expr1 || expr2 | Renvoieexpr1 si elle peut être convertie entrue et renvoieexpr2 sinon. Lorsqu'il est utilisé avec des valeurs booléennes,|| renvoietrue si l'un des deux opérandes vauttrue etfalse si les deux valentfalse . |
NON logique (! ) | !expr | Renvoiefalse si son unique opérande peut être converti entrue , renvoietrue sinon. |
Les expressions équivalentes àfalse
sont celles qui sont évaluées avec la valeurnull
,0
,NaN
, la chaîne vide (""
), ouundefined
.
Les exemples de code suivant illustrent l'utilisation de l'opérateur ET logique&&
.
const a1 = true && true; // t && t renvoie trueconst a2 = true && false; // t && f renvoie falseconst a3 = false && true; // f && t renvoie falseconst a4 = false && 3 === 4; // f && f renvoie falseconst a5 = "Chat" && "Chien"; // t && t renvoie Chienconst a6 = false && "Chat"; // f && t renvoie falseconst a7 = "Chat" && false; // t && f renvoie false
Les exemples de code suivant illustrent l'utilisation de l'opérateur OU logique||
.
const o1 = true || true; // t || t renvoie trueconst o2 = false || true; // f || t renvoie trueconst o3 = true || false; // t || f renvoie trueconst o4 = false || 3 === 4; // f || f renvoie falseconst o5 = "Chat" || "Chien"; // t || t renvoie Chatconst o6 = false || "Chat"; // f || t renvoie Chatconst o7 = "Chat" || false; // t || f renvoie Chat
Les exemples de code suivant illustrent l'utilisation de l'opérateur NON logique!
.
const n1 = !true; // !t renvoie falseconst n2 = !false; // !f renvoie trueconst n3 = !"Chat"; // !t renvoie false
Évaluation en court-circuit
Les expressions logiques étant évaluées de gauche à droite, le moteur d'exécution utilise les courts-circuits dans les cas suivants :
false && nimportequoi
sera court-circuitée pour être évaluée enfalse
.true || nimportequoi
sera court-circuitée pour être évaluée entrue
.
Les règles logiques garantissent la véracité de ces évaluations. On notera que l'opérandenimportequoi
dans les expressions précédentes n'estpas évalué et que tout effet de bord lié à cette évaluation n'aura donc pas lieu.
Pour le deuxième exemple, on pourra utiliserl'opérateur de coalescence des nuls (??
) qui fonctionne comme||
, en renvoyant uniquement la deuxième expression lorsque la première estéquivalente ànull
, c'est-à-dire qu'elle vautnull
ouundefined
.
L'opérateur de coalescence des nuls est donc une meilleure solution lorsqu'il s'agit de fournir des valeurs par défaut, notamment lorsque''
ou0
sont des valeurs valides.
Opérateurs pour les grands entiers
La plupart des opérateurs numériques peuvent être utilisés avec des valeurs de typeBigInt
(qui représentent des grands entiers).
// Addition de grands entiersconst a = 1n + 2n; // 3n// Une division entre grands entiers est arrondie à zéroconst b = 1n / 2n; // 0n// Il n'y a pas de troncature avec les opérations binairesconst c = 40000000000000000n >> 2n; // 10000000000000000n
L'opérateur de décalage à droite non-signé (>>>
) est une exception : il n'est pas défini pour les valeurs, car les grands entiers n'ont pas une largeur binaire fixe et n'ont donc pas de bit le plus haut.
const d = 8n >>> 2n; // TypeError: BigInts have no unsigned right shift, use >> instead
Il n'est pas possible d'interchanger des nombres et des grands entiers. On ne peut pas les mélanger dans un même calcul.
const a = 1n + 2; // TypeError: Cannot mix BigInt and other types
En effet,BigInt
n'est pas un sous-ensemble ou un sur-ensemble du type numérique. Les grands entiers ont une plus grande précision mais ne peuvent pas représenter de nombres décimaux. Toute conversion implicite dans un sens ou l'autre entraînerait une perte de précision. Il faudra utiliser une conversion explicite pour indiquer avec quel type on souhaite effectuer l'opération.
const a = Number(1n) + 2; // 3const b = 1n + BigInt(2); // 3n
Il est aussi possible de comparer des grands entiers avec des nombres.
const a = 1n > 2; // falseconst b = 3 > 2n; // true
Opérateurs pour les chaînes de caractères
En complément des opérateurs de comparaison qui peuvent être utilisés avec les chaînes de caractères, on peut également utiliser l'opérateur de concaténation (+
) afin de concaténer deux chaînes de caractères ensemble et renvoyer le résultat de cette concaténation.
Ainsi :
console.log("ma " + "chaîne"); // affichera "ma chaîne" dans la console.
L'opérateur d'affectation raccourci+=
peut également être utilisé pour concaténer des chaînes.
Par exemple :
let maChaine = "alpha";maChaine += "bet"; // sera évalué en "alphabet" et affectera cette valeur à maChaine.
Opérateur conditionnel (ternaire)
L'opérateur conditionnel est le seul opérateur JavaScript à prendre trois opérandes. Il permet de se résoudre en une valeur ou en une autre selon une condition donnée. Sa syntaxe est la suivante :
condition ? val1 : val2;
Sicondition
est vraie, l'expression sera résolue avec la valeur deval1
. Sinon, elle sera résolue avec la valeur deval2
. L'opérateur conditionnel peut être utilisé à tout endroit où un opérateur standard peut être utilisé.
Par exemple :
const statut = age >= 18 ? "adulte" : "mineur";
Cette instruction affecte la valeur"adulte"
à la variablestatut
siage
est supérieur ou égal à 18. Sinon, c'est la valeur"mineur"
qui est affectée àstatut
.
Opérateur virgule
L'opérateur virgule (,
) évalue les deux opérandes et renvoie la valeur du dernier opérande. Cet opérateur est généralement utilisé dans les bouclesfor
afin de mettre à jour plusieurs variables à chaque itération de la boucle. L'utiliser ailleurs est considéré comme une mauvaise pratique et on privilégiera plusieurs instructions séparées.
Par exemple, si on aa
qui est un tableau en deux dimensions avec 10 éléments pour chaque ligne. Le code qui suit utilise l'opérateur virgule afin de mettre à jour deux variables à la fois. Dans cet exemple, on affiche les valeurs des éléments situés sur la diagonale du tableau :
const x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];const a = [x, x, x, x, x];for (let i = 0, j = 9; i <= j; i++, j--) { // ^ console.log(`a[${i}][${j}]= ${a[i][j]}`);}
Opérateurs unaires
Un opérateur unaire fonctionne avec un seul opérande.
delete
L'opérateurdelete
permet de supprimer une propriété d'un objet. La syntaxe correspondante est :
delete objet.propriete;delete objet[clePropriete];delete objet[indice];
Oùobjet
est le nom d'un objet,propriete
est une propriété existante,clePropriete
est une chaîne de caractères ou un symbole faisant référence à une propriété existante.
Lorsque l'opérateurdelete
réussit, la propriété est supprimée de l'objet et toute tentative d'accès ultérieur renverraundefined
. L'opérateurdelete
renvoietrue
si l'opération est possible etfalse
sinon.
delete Math.PI; // renvoie false (on ne peut pas supprimer des propriétés non-configurables)const monObj = { h: 4 };delete monObj.h; // renvoie true (on peut supprimer des propriétés personnalisées)
Supprimer des éléments de tableau
Comme les tableaux sont également des objets, il est techniquement possible de supprimer des éléments avecdelete
. Il s'agit toutefois de quelque chose considéré comme une mauvaise pratique. En effet, lorsqu'on supprime une propriété d'un tableau, la longueur n'est pas modifiée et les autres éléments ne sont pas réindexés. Pour un comportement analogue, mieux vaudra réécrire la valeur de l'élément avecundefined
. Pour manipuler un tableau, on utilisera plutôt les méthodes associées commesplice()
.
typeof
L'opérateurtypeof
s'utilise de la façon suivante :
typeof operande;
L'opérateurtypeof
renvoie une chaîne de caractères qui indique le type de l'opérande non-évalué.operande
est une chaîne de caractères, une variable, un mot-clé ou un objet dont on souhaite connaître le type. On peut utiliser des parenthèses autour de l'opérande.
Prenons la définition des variables suivantes :
const maFonction = new Function("5 + 2");const forme = "rond";const taille = 1;const toto = ["Pomme", "Mangue", "Orange"];const jour = new Date();
L'opérateurtypeof
renvoie les résultats suivants pour ces différentes variables :
typeof maFonction; // renvoie "function"typeof forme; // renvoie "string"typeof taille; // renvoie "number"typeof toto; // renvoie "object"typeof jour; // renvoie "object"typeof inexistant; // renvoie "undefined"
Pour les mots-cléstrue
etnull
, l'opérateurtypeof
renvoie les résultats suivants :
typeof true; // renvoie "boolean"typeof null; // renvoie "object"
Pour un nombre ou une chaîne de caractères,typeof
renverra les résultats suivants :
typeof 62; // renvoie "number"typeof "Coucou monde"; // renvoie "string"
Pour les valeurs qui sont des propriétés,typeof
renvoie le type de la valeur contenue dans la propriété :
typeof document.lastModified; // renvoie "string"typeof window.length; // renvoie "number"typeof Math.LN2; // renvoie "number"
Pour les méthodes et fonctions,typeof
renverra les résultats suivants :
typeof blur; // renvoie "function"typeof eval; // renvoie "function"typeof parseInt; // renvoie "function"typeof shape.split; // renvoie "function"
Pour les objets natifs,typeof
renverra les résultats suivants :
typeof Date; // renvoie "function"typeof Function; // renvoie "function"typeof Math; // renvoie "object"typeof Option; // renvoie "function"typeof String; // renvoie "function"
void
L'opérateurvoid
s'utilise d'une des deux façons suivantes :
void (expression)void expression
L'opérateurvoid
indique une expression à évaluer sans renvoyer de valeur.expression
est une expression JavaScript à évaluer. Les parenthèses autour de l'expression sont optionnelles, mais c'est une bonne pratique que de les utiliser.
Opérateurs relationnels
Un opérateur relationnel compare ses opérandes et renvoie une valeur booléenne selon le résultat de la comparaison.
in
L'opérateurin
renvoietrue
si la propriété indiquée par l'opérande gauche est présente dans l'objet indiqué par l'opérande droit. La syntaxe est la suivante :
nomPropriete in nomObjet;
oùnomPropriete
est une chaîne de caractères, une valeur numérique ou un symbole représentant une propriété, etnomObjet
est le nom de l'objet.
Voici quelques exemples utilisant l'opérateurin
.
// Tableauxconst arbres = ["séquoia", "laurier", "cèdre", "chêne", "érable"];0 in arbres; // renvoie true3 in arbres; // renvoie true6 in arbres; // renvoie false"séquoia" in arbres; // renvoie false (il faut indiquer l'indice, pas la// valeur)"length" in arbres; // renvoie true (length est une propriété native)// Objets natifs"PI" in Math; // renvoie trueconst maChaine = new String("corail");"length" in maChaine; // renvoie true// Objets personnalisésconst maVoiture = { fabricant: "Honda", modele: "Accord", annee: 1998 };"fabricant" in maVoiture; // renvoie true"modele" in maVoiture; // renvoie true
instanceof
L'opérateurinstanceof
renvoietrue
si l'objet porté par l'opérande gauche est du type indiqué par l'opérande droit. La syntaxe est :
nomObjet instanceof typeObjet;
oùnomObjet
est le nom de l'objet dont on souhaite vérifier le type ettypeObjet
est le type en question, commeDate
ouArray
.
On utiliserainstanceof
lorsqu'on souhaite confirmer le type d'un objet à l'exécution. On pourra par exemple gérer différemment une exception selon son type.
Dans l'exemple qui suit, on utiliseinstanceof
pour déterminer sijour
est un objetDate
. Commejour
est bien un objet de typeDate
, les instructions conditionnelles sont exécutées.
const jour = new Date(1995, 12, 17);if (jour instanceof Date) { // instructions à exécuter}
Expressions de base
Tous les opérateurs manipulent en fin de compte une ou plusieurs expressions de base. Ces expressions de base utilisentles identifiants etles littéraux, et quelques autres éléments que nous introduisons ci-après. Ils sont décrits plus en détails dans leur page de référence.
this
Le mot-cléthis
fait référence à l'objet courant. En général,this
fait référence à l'objet appelant d'une méthode.this
pourra être utilisé avec la notation utilisant le point ou celle utilisant les crochets :
this["nomPropriete"];this.nomPropriete;
Prenons une fonctionvalider()
qui valide la propriétévalue
d'un objet en fonction d'un minimum et d'un maximum :
function valider(obj, min, max) { if (obj.value < min || obj.value > max) { console.log("Valeur invalide !"); }}
On peut appelervalider()
pour un élément de formulaire sur le gestionnaire d'évènementonChange
en utilisantthis
afin de passer le contrôle du formulaire :
<p>Saisissez un nombre entre 18 et 99 :</p><input type="text" name="age" size="3" onChange="valider(this, 18, 99);" />
Opérateur de groupement
L'opérateur de groupement,( )
, contrôle la précédence de l'évaluation dans une expression. On peut ainsi prioriser certaines opérations par rapport à d'autres et passer outre la précédence par défaut. Dans l'exemple qui suit, on utilise les parenthèses pour que l'addition ait lieu avant la multiplication.
const a = 1;const b = 2;const c = 3;// Précédence par défauta + b * c; // 7// Qui est évalue par défaut commea + (b * c); // 7// On passe outre cette précédence pour// additionner avant de multiplier(a + b) * c; // 9// Ce qui est équivalent àa * c + b * c; // 9
new
L'opérateurnew
peut être utilisé afin de créer une instance d'un objet (que ce type d'objet soit défini dans le script ou par l'environnement d'exécution). On utiliseranew
comme suit :
const nomObjet = new TypeObjet(param1, param2, /* …, */ paramN);
super
Le mot-clésuper
est utilisé pour appeler des fonctions sur le parent d'un objet. Il est utile lorsqu'on manipule desclasses afin d'appeler le constructeur parent par exemple.
super([arguments]); // On appelle le constructeur parent.super.fonctionSurLeParent([arguments]);