Copyright © 2017-2025 Yves MARCOUX; dernière modification de cette page : 2025-05-25.

SCI6373 Programmation documentaire

Introduction aux expressions JavaScript

Index de ce texte

Yves MARCOUX - EBSI - Université de Montréal


Table des matières

Introduction (p. 2)

Mode de lecture recommandé (p. 2)

Activation et réglage de la console JavaScript (p. 2)

Lecture active (p. 3)

Interaction avec la console (p. 3)

Les différentes formes de JavaScript (p. 4)

Différents environnements (p. 4)

Énoncés (ou commandes) et scripts (ou programmes) (p. 5)

Expressions (p. 6)

Valeurs JavaScript, valeurs simples (p. 7)

Constantes (p. 7)

Opérations simples sur valeurs simples (p. 9)

Variables (p. 10)

Règles sur les noms de variables (p. 11)

Utilisations types des variables (p. 12)

Enchaînement d’expressions (p. 13)

Parenthésage (p. 14)

Priorité des opérateurs (p. 15)

Sous-expressions et LHS (p. 17)

Autres opérations (p. 18)

Comparaisons, valeurs booléennes (p. 18)

Opérateurs booléens (p. 20)

Le choix conditionnel « ? : » (p. 21)

- et + unaires (p. 22)

Opérations à syntaxe particulière (p. 23)

Opérations mathématiques (p. 23)

Opérations sur les chaînes de caractères (p. 24)

Interactions de base avec l’utilisatrice (p. 27)

Environnement, membres (p. 29)

Objets (p. 32)

Opérateur « . », chemins d’accès (p. 35)

Fonctions (p. 38)

Règles sur les noms de membre (p. 41)

Propriétés et méthodes (p. 41)

Autres utilisations de l’opérateur « . » (p. 41)

Annexe (p. 42)


Introduction

Ce texte présente certains concepts de base du JavaScript (JS) :

Il propose une terminologie associée à ces concepts et illustre comment ceux-ci peuvent s’exprimer dans des expressions JavaScript, lesquelles sont utilisées pour former des énoncés – ou instructions, ou commandes – JavaScript, qui à leur tour, forment des programmes – ou scripts – JavaScript.

Mode de lecture recommandé

Ce texte contient beaucoup d’exemples d’énoncés JS. Le mode de lecture recommandé est une lecture « active », qui consiste à « essayer » vous-même les exemples en les faisant exécuter au fur et à mesure que vous les rencontrez dans le texte. Le plus simple est de les copier-coller à partir du présent texte vers ce qu’on appelle la console JavaScript de notre navigateur Web, qui doit d’abord être activée et réglée adéquatement.

Activation et réglage de la console JavaScript

Capsule vidéo

Une capsule vidéo démontre la procédure pour les navigateurs Firefox, Edge et Chrome.

Dans les environnements informatiques modernes, il y a de multiples façons de faire exécuter des énoncés JS. L’une d’elles est d’utiliser la composante d’un navigateur Web appelée console JavaScript. Si vous lisez ce texte sur le Web, nous recommandons d’utiliser la console du navigateur dans lequel vous lisez actuellement ce texte. Notez que cela exige que vous fassiez la lecture sur un ordinateur, et non sur une tablette ou un téléphone.

La capsule vidéo illustre la procédure pour tous les navigateurs courants, mais en voici un résumé pour Firefox.

Pour Firefox

  1. Faire Outils → Outils du navigateur → Outils de développement web → onglet Console (ou Ctrl-Maj-K, ou F12). Ceci ouvre la fenêtre des outils de développement Web.
  2. Cliquez sur les dans le bandeau de tête de la fenêtre qui vient de s’ouvrir, puis sélectionnez la disposition désirée. Nous recommandons l’option Ancrer à droite.
  3. Sélectionnez l’onglet Console s’il n’est pas déjà actif.
  4. Vers le haut de la fenêtre, si les mots Avertissements et Informations apparaissent soulignés, cliquez dessus pour désactiver les messages correspondants. Ceci évite que la console ne soit encombrée de nombreux messages peu utiles.
  5. Vérifiez le fonctionnement de la console en tapant 2+2 suivi de la touche Entrée. Vous obtiendrez la réponse 4.
  6. Dans la console, tapez les mots autoriser le collage, suivis de Entrée. Ignorez le message d’erreur qui s’affiche.

Vous pouvez maintenant soit saisir des énoncés JavaScript au clavier, soit les copier-coller d’ailleurs (par exemple du présent texte). L’effet de l’étape 6 est enregistré dans votre profil Firefox, elle n’est donc requise qu’une seule fois.

Des problèmes ?

Pour un accompagnement plus complet, consultez la capsule vidéo.

Toutes les manipulations nécessaires, pour tous les navigateurs, seront effectuées en classe au premier cours.

Lecture active

Maintenant que la console JavaScript est activée et réglée pour accepter le copier-coller, vous pouvez faire une lecture « active », tel que recommandé. La lecture active consiste à essayer à la console tous les exemples du texte.

Le plus simple pour « essayer » les exemples à la console est de les copier-coller (Ctrl+C / Ctrl+V) à partir de la version Web du texte (probablement celle que vous êtes en train de lire). Essayez-le avec l’exemple qui suit. Vous ne copiez que la première ligne; la seconde ligne, en vert, est la réponse que vous obtiendrez à la console après avoir appuyé sur Entrée :

Math.PI
3.141592653589793

En plus de copier-coller les exemples tels quels, vous êtes bien sûr aussi encouragée à les modifier à la console et à observer l’effet obtenu, de même qu’à formuler vos propres énoncés; c’est la meilleure façon d’apprendre et de bien comprendre les notions présentées.

Interaction avec la console

La console fonctionne en mode commande : on saisit une commande, on appuie sur Entrée et la console affiche la réponse. Si vous tapez 2+2, vous obtiendrez la réponse 4. En fait, vous aurez probablement remarqué que la réponse s’affiche avant même qu’on n’appuie sur Entrée, mais appuyer sur Entrée « officialise » la commande et permet de passer à la suivante.

Les « commandes » ou « instructions » que l’on inscrit à la console JS sont des énoncés JS. Un énoncé JS est une « phrase » du langage JS. À ce titre, il est formé de mots, de signes de ponctuation et d’autres symboles, dont l’agencement doit respecter une certaine syntaxe, propre au langage JS. Chaque énoncé exprime, dans ce langage, une ou plusieurs tâches, ou opérations, à effectuer. Lorsqu’on appuie sur Entrée, un interprète JS, intégré au navigateur Web, exécute l’énoncé inscrit à la console en effectuant la ou les opérations représentées par l’énoncé.

Une session à la console JS d’un navigateur Web (la période entre l’ouverture et la fermeture de la console) est un dialogue entre l’utilisatrice, qui inscrit des énoncés JS dans la console, et l’interprète JS intégré au navigateur, qui exécute ces énoncés et en affiche le résultat. Par exemple, tout à l’heure, le dialogue suivant a eu lieu :

2+2
4

Nous affichons en vert le résultat retourné par l’interprète JS à la console en réponse à un énoncé. Les résultats d’interaction montrés dans le texte sont ceux qu’on obtient avec Firefox. Si vous utilisez un autre navigateur, ils pourraient à l’occasion être légèrement différents.

Les touches ↑ et ↓ du clavier permettent de naviguer dans l’historique des énoncés que l’on a soumis précédemment. Après qu’on ait rappelé un énoncé de l’historique, on peut le modifier avant de lancer de nouveau l’exécution en appuyant sur Entrée.

Si on appuie sur Entrée après avoir tapé un énoncé incomplet, l’interprète JS ne répond rien, mais attend qu’on le complète sur la ligne suivante et qu’on appuie de nouveau sur Entrée. Si on inscrit plus d’un énoncé sur la même ligne avant d’appuyer sur Entrée, l’interprète les exécute tous, mais n’affiche que le résultat du dernier. C’est aussi ce qui se produit lorsqu’on copie-colle plusieurs lignes d’un coup.

Plus techniquement : La console JS est un outil de type « REPL », qui veut dire read-eval-print loop, dont la caractéristique est d’accepter un énoncé d’un langage de programmation (habituellement un seul énoncé), de l’exécuter et d’en afficher immédiatement le résultat, avant de retomber en attente d’un prochain énoncé à exécuter, un peu à la manière d’une calculette. Des outils REPL existent pour la plupart des langages de programmation, sous forme d’applications locales ou en ligne. Un REPL gratuit pour le JavaScript est disponible au <https://repljs.com/>.

Comme il sera illustré en classe dès le premier cours, la console JS est un peu comme un guichet d’accès « secret » aux entrailles du navigateur, qui permet d’effectuer « de l’intérieur » des opérations qui se répercutent immédiatement sur la fenêtre de navigation.


Les différentes formes de JavaScript

Différents environnements

JavaScript (aussi appelé ECMAScript) est un des langages de programmation les plus répandus dans le monde. Intimement lié au HTML (en particulier HTML5), c’est le langage de programmation Web par excellence. Il est reconnu par tous les navigateurs Web et on le retrouve dans des millions de pages HTML sur le Web.

Mais le Web n’est qu’un des environnements où on retrouve le JS. On le retrouve également dans des documents PDF, formulaires de bases de données, applications Web côté serveur, dessins SVG, documents bureautiques, pour ne nommer que ceux-là.

Dans la spécification normalisée qui le décrit, JavaScript est défini de façon « désincarnée », indépendamment d’un environnement spécifique. Bien qu’il soit possible d’apprendre le langage sans référence à un environnement précis, il est beaucoup plus facile de le faire dans le cadre d’un environnement particulier.

Dans ce cours, l’environnement d’apprentissage choisi est celui des navigateurs Web. Un choix qui s’explique par l’utilité de connaître cet environnement et par le fait qu’il suffit d’un navigateur Web et d’un éditeur de textes pour passer à la pratique, deux outils omniprésents dans les systèmes informatiques courants.

Énoncés (ou commandes) et scripts (ou programmes)

Même si on peut faire exécuter des énoncés JS un par un à la console d’un navigateur Web, le JavaScript se présente habituellement sous la forme non pas d’un seul énoncé JS, mais de scripts (ou programmes), formés de plusieurs énoncés, inscrits l’un après l’autre dans un fichier texte.

Quand un script JS s’exécute dans un navigateur Web, les énoncés qu’il contient sont exécutés par le même interprète JS que celui qui traite les énoncés inscrits à la console. Simplement, les énoncés proviennent du script, et non de la console.

Une des formes souvent rencontrées sur le Web est celle d’un script imbriqué dans une page HTML. Voici un exemple de page HTML contenant un script JavaScript imbriqué, telle qu’elle pourrait se présenter dans un éditeur de texte typique, comme Notepad++ :

<!DOCTYPE html>
<html>
<!-- Exemple typique de page HTML scriptée. -->
    <head>
        <title>Dites-moi vite bonjour&nbsp;!</title>
    </head>
    <body>
        <h1>Dites-moi vite bonjour&nbsp;!</h1>
        <form action="javascript:traiterFormulaire();">
            <p>SVP, entrez votre nom&nbsp;:
                <input id="ctrlEntrée" type="text">
                <input type="submit" value="OK">
            </p>
        </form>
        <hr>
        <div id="sortie"></div>
        <script>
// Initialisation de la page :
let ctrlEntrée = document.getElementById("ctrlEntrée");
let sortie = document.getElementById("sortie");
let heureDébut = new Date();
ctrlEntrée.select();

function traiterFormulaire() {
// Lecture des données :
    let nom = ctrlEntrée.value;
    let heureActuelle = new Date();

// Calculs :
    let temps = (heureActuelle - heureDébut) / 1000;
    let message = "Bonjour " + nom + "&nbsp;! J’espère que vous allez bien.<br>";
    message += `Vous avez pris ${temps} secondes pour répondre.`;

// Affichage des résultats :
    sortie.innerHTML = message;

// Préparation de la prochaine interaction :
    heureDébut = heureActuelle;
    ctrlEntrée.select();
};
        </script>
    </body>
</html>

Cet exemple est disponible ici, si jamais vous voulez l’essayer (facultatif).

On remarque tout de suite qu’une coloration syntaxique est appliquée par l’éditeur. Ces couleurs ne se retrouvent évidemment pas dans le fichier texte qu’est la page HTML, puisqu’un fichier texte ne contient que des caractères sans aucun attribut de présentation. Les couleurs sont ajoutées par l’éditeur de texte, exclusivement dans l’affichage présenté à l’utilisatrice, et simplement pour mettre en évidence les différentes constructions syntaxiques du ou des langages utilisés.

Ici, il y a deux langages utilisés : HTML et JS. Il y a donc deux schèmes de coloration syntaxique qui se « superposent ». Le JS est présenté sur fond bleu pâle, le reste correspond au HTML. De plus, chaque type de construction syntaxique de l’un ou l’autre des deux langages a ses propres couleur et formatage.

Si vous connaissez le HTML, vous reconnaissez les constructions habituelles que sont les éléments <head>, <title>, <body>, etc. L’élément <script>, qui est peut-être nouveau pour vous, sert à « héberger » le JS de façon imbriquée dans la page HTML. À l’intérieur de cet élément, ce n’est plus du HTML que l’on retrouve, mais bien du code répondant aux règles syntaxiques du JS.

À part les commentaires, affichés en vert, ce code n’est rien d’autre qu’une suite d’énoncés JS, chacun se terminant par un point-virgule ; (qui peut parfois être omis). Comme vous pouvez voir, chaque énoncé est placé sur sa propre ligne de texte. Ce n’est pas obligatoire, mais c’est la pratique la plus répandue, notamment parce qu’elle favorise la lisibilité du code.

Les énoncés JS sont donc les briques avec lesquelles on construit les programmes ou scripts JS, qui sont de véritables applications informatiques capables d’interagir avec des utilisatrices et d’accomplir des tâches utiles.

Expressions

Les expressions JS (ou, dans ce texte, simplement « expressions ») sont un élément crucial de la composition des énoncés JS. Toute expression JS (suivie facultativement d’un point-virgule ";") est en elle-même un énoncé et, sauf de très rares exceptions, un énoncé JS contient toujours au moins une expression. La notion d’expression est donc fondamentale en JS et c’est la raison pour laquelle le présent texte lui est entièrement consacré. Il présente les formes les plus courantes d’expressions JS.

Le point-virgule en fin d’énoncé est presque toujours facultatif; aussi nous permettons-nous donc le plus souvent de l’omettre pour alléger nos exemples.

Les expressions JS doivent respecter une certaine syntaxe, définie par le JS. Une expression qui respecte cette syntaxe est dite bien formée. Le bien-formé d’une expression ne concerne que sa syntaxe, mais ne garantit pas qu’elle s’exécutera toujours sans erreur. C’est la sémantique d’une expression, ce qu’elle signifie comme opération ou enchaînement d’opérations, qui détermine si elle peut s’exécuter sans erreur et, le cas échéant, quel est son effet.

Ce texte présente quelques éléments tant de syntaxe que de sémantique concernant les expressions : d’une part, comment on doit les écrire (syntaxe) et, d’autre part, ce qu’elles font (sémantique).


Valeurs JavaScript, valeurs simples

Une expression JS exprime un « calcul » – au sens très large – devant être effectué sur certaines données, auxquelles sont éventuellement appliquées certaines opérations. Autant les données que le résultat des opérations sont ce qu’on appelle des valeurs JavaScript.

Le concept de valeur JS est très intuitif. Il s’agit d’un élément de donnée élémentaire et atomique (traité comme un tout) pouvant être manipulé par le JS.

Comme un expression JS exprime un calcul formulé en termes de données et d’opérations, le résultat de l’expression elle-même est aussi toujours une valeur JS.

Prenons l’exemple suivant :

34 + 52
86

L’expression contient deux éléments de données : les nombres 34 et 52, et une opération, l’addition, représentée par le "+", qui doit être appliquée aux deux nombres. Le résultat, affiché ici par l’interprète en réponse à l’expression, est le nombre 86. Les trois nombres, 34, 52 et 86, sont trois exemples de valeur JS.

À part quelques valeurs dites « autonymes », sur lesquelles nous aurons l’occasion de revenir, une valeur JS ne peut être que l’une des trois choses suivantes :

  1. une valeur numérique,
  2. une chaîne de caractères (ou valeur caractère),
  3. un pointeur (ou une référence) à un objet.

Une valeur qui n’est pas un pointeur à un objet est appelée une valeur simple. Une valeur simple est donc une valeur numérique, une chaîne de caractères ou une des valeurs autonymes.

Un pointeur à un objet est comme une adresse numérique interne à l’interprète JS, que celui-ci peut utiliser pour accéder à un objet stocké en mémoire. Un objet n’est pas lui-même une valeur directement manipulable par un script. Un script ne peut manipuler directement que des pointeurs à des objets. Nous reviendrons plus loin sur les objets, mais nous concentrons pour le moment sur les valeurs simples.


Constantes

Les constantes sont un premier type d’expressions JS, qui servent à dénoter des valeurs simples fixes (numériques, caractères ou autonymes). En tant qu’expressions, les constantes ne contiennent aucune opération; elles n’expriment en fait qu’une seule valeur JS. Comme toute expression JS, une constante retourne un résultat, qui est simplement la valeur JS exprimée par la constante. Un exemple clarifiera les choses :

345
345

L’expression est la constante 345, qui représente la valeur numérique 345. Le résultat retourné par l’exécution de l’expression est donc la valeur numérique 345, que l’interprète JS nous affiche à la console.

Les constantes numériques s’écrivent de la façon habituelle pour les nombres (avec le point comme séparateur décimal, et non la virgule) :

345.67
345.67

100.000
100

Les constantes caractères doivent être écrites entre guillemets (simples ou doubles) :

"Allô"
"Allô"

'Bonjour'
"Bonjour"

Quand une expression est une constante, JS semble simplement recopier ce qui est tapé, mais il y a parfois certaines différences. C’est que JS interprète véritablement la constante comme une expression, dont il affiche la valeur résultante. Par exemple, vous pouvez constater que, même si l’on spécifie trois zéros après le point dans 100.000, JS nous retourne la valeur sous sa forme la plus simple, sans les décimales. De même, la valeur caractère 'Bonjour' nous est retournée avec le guillemet double comme délimiteur.

Nous verrons plus tard dans le cours certaines particularités sur la façon d’écrire les constantes numériques et caractères, mais les formes ci-dessus nous suffisent pour le moment.

Les valeurs autonymes (mentionnées ci-dessus) constituent – après les valeurs numériques et caractère – la troisième sorte de valeurs simples en JS. Les valeurs autonymes sont ainsi appelées parce qu’elles « se désignent elles-mêmes ». Elles sont parfois aussi qualifiées d’« ésotériques », parce qu’elles ont un rôle ou comportement spécial dans le langage.

Les valeurs autonymes ne sont connues en JS que par les constantes qui les représentent.

Voici les constantes correspondant aux principales valeurs autonymes :

true
false
undefined
null
NaN
Infinity

Quand l’interprète JS veut afficher une des valeurs autonymes, il affiche simplement à la console la constante qui la représente. Ainsi, si vous tapez à la console n’importe laquelle des constantes ci-dessus, vous obtenez exactement la même chose en réponse. (Allez-y, essayez-le !)

Nous reviendrons plus loin sur le rôle de certaines des valeurs autonymes. Retenons pour le moment qu’elles ont chacune un rôle important au sein du langage JS.

Un petit nombre de constantes possèdent leur propre nom dans le langage JS. L’une d’elles est la constante mathématique π (3.14159…), qu’on peut désigner en JS par l’expression (déjà entrevue ci-dessus) Math.PI :

Math.PI
3.141592653589793


Opérations simples sur valeurs simples

Les quatre opérations arithmétiques communes +, -, × et ÷ peuvent être appliquées aux valeurs numériques. La multiplication et la division, cependant, s’expriment avec les symboles * et / respectivement, plutôt qu’avec les symboles usuels. On parle d’« opération » pour désigner la fonction arithmétique elle-même, et d’« opérateur » pour désigner le symbole graphique utilisé pour exprimer l’opération dans le langage JS. On dira par exemple que l’opération de multiplication est représentée par l’opérateur *.

Les valeurs auxquelles une opération s’applique sont appelées les opérandes ou arguments. Les quatre opérations arithmétiques mentionnées s’appliquent toutes à deux arguments : un à gauche de l’opérateur et l’autre à droite.

Deux constantes jointes par un opérateur arithmétique mitoyen forment aussi une expression JS :

345+3
348

10 -12
-2

32* 0.5
16

25 / 0.25
100

80*1
80

Comme on peut constater, la présence d’espaces avant ou après l’opérateur ne change rien.

Concaténation de chaînes de caractères

L’opérateur + appliqué à des valeurs caractères effectue une opération différente de l’addition : la concaténation de chaînes de caractères, c’est-à-dire le « collage » des deux chaînes l’une à la suite de l’autre :

"ab" + "c"
"abc"

'4'+'ab'
"4ab"

"9" + '9'
"99"

"2 -"+"7"
"2 -7"

La constante "" (tout comme '') dénote la chaîne vide, de longueur nulle, ne contenant aucun caractère, mais qui est bel et bien une valeur caractère. La chaîne vide se comporte dans la concaténation comme le 0 dans l’addition :

"abc" + ""
"abc"

'' + "ABC"
"ABC"

""+""
""

'' + ''
""

Conversion automatique

Nous verrons en classe plusieurs cas où une valeur JS est automatiquement convertie d’un type à un autre. Un cas très utile est celui de la concaténation d’une chaîne avec une valeur numérique. La valeur numérique est simplement transformée en chaîne de caractères, puis la concaténation est effectuée :

'abc' + 99
"abc99"

12/13 + " est tout un nombre !"
"0.9230769230769231 est tout un nombre !"


Variables

Une variable est un endroit de stockage où peut être enregistrée exactement une valeur JS, de façon à pouvoir être « rappelée » et réutilisée plus tard. Lorsque, comme programmeuse, on élabore un script qui consistera en une séquence de plusieurs instructions, il est extrêmement utile de pouvoir stocker en mémoire certaines valeurs de façon à pouvoir les réutiliser dans des étapes ultérieures : les variables servent exactement à cela.

Une variable est identifiée par un nom, qui lui est exclusif, et grâce auquel on pourra « rappeler » la valeur qu’elle contient. On crée une variable et on y place une valeur avec un énoncé de la forme :

nom = expression

par exemple :

x = 42
42

ou :

x = 84 * 0.5
42

On appelle ce genre d’expression assignation ou affectation de variable. L’opérateur "=" est lui-même appelé l’opérateur d’assignation ou d’affectation. On voit souvent les assignations précédées d’un des mots-clés const, let ou var. Ces mots-clés sont le plus souvent facultatifs. Leur usage sera discuté en classe.

Une assignation de variable comporte une expression après le "=", mais est aussi elle-même une expression. Comme expression, l’assignation retourne la valeur qui vient tout juste d’être stockée dans la variable; c’est d’ailleurs pour cette raison que JS nous affiche cette valeur en réponse à l’assignation.

Une fois qu’une variable a été définie – c’est-à-dire qu’une valeur lui a été assignée – on peut « rappeler » sa valeur en utilisant comme expression le nom de la variable :

x
42

Un nom de variable définie constitue donc une expression bien formée. Un nom de variable peut remplacer une constante dans les opérations de base que nous avons vues jusqu’ici :

x + 100
142

x+x
84

Bien sûr, ça marche aussi avec les valeurs de type caractère :

nom = "Jojo"
"Jojo"

"Bonjour "+nom
"Bonjour Jojo"

Si on référence une variable qui n’a jamais été définie, on obtient un message d’erreur; par exemple :

inconnue
Uncaught ReferenceError: inconnue is not defined

Règles sur les noms de variables

Les noms que l’on peut donner aux variables dans une assignation doivent être composés de lettres (majuscules ou minuscules, avec ou sans accents ou autres signes diacritiques), de chiffres, de caractères de soulignement "_" et de signes de dollar "$". Ils doivent commencer par une lettre. Il n’y a a priori pas de limite sur leur longueur. Voici des exemples corrects :

a
nombreDeLivres
leçon$2
Été_2020

La casse des lettres (majuscule vs minuscule) est significative : A ne désigne pas la même variable que a. Notons que le tiret "-" n’est pas permis dans un nom de variable. Voici quelques exemples incorrects :

212x commence par un chiffre
n#clients le caractère # est interdit
leçon 24 l’espace est interdite
Été-2020 le tiret - est interdit

Plusieurs mots-clés réservés ne peuvent pas être utilisés comme nom de variable en JS, incluant bien sûr le nom des valeurs autonymes. D’autres noms devraient être évités, dont ceux des « membres statutaires » de l’environnement, dont nous parlerons plus loin. Une liste complète peut être consultée ici.

Même si les chances de tomber par hasard sur un nom « interdit » sont faibles, il est de bonne pratique de vérifier qu’un nom envisagé est « libre » en le tapant comme expression à la console avant de l’utiliser :

saison
Uncaught ReferenceError: saison is not defined

Certaines de ces restrictions sont levées si l’on déclare la variable, via un énoncé const, let ou var. Ce point sera discuté en classe.

On peut noter ici que, pour une programmeuse francophone, l’utilisation de noms de variables construits à partir du français confère une certaine assurance (toute relative, bien sûr) contre une collision fortuite avec un des noms interdits, puisque ces derniers sont construits à partir de l’anglais. Soulignons à ce sujet que l’utilisation de signes diacritiques dans les noms de variables est permise, comme certains de nos exemples le démontrent.

Utilisations types des variables

Stockage de résultats intermédiaires

Une des utilisations de base des variables est pour stocker les résultats intermédiaires de calculs, un peu comme la fonction « mémoire » des calculatrices; sauf qu’en JS, on a virtuellement une « infinité » de mémoires à notre disposition. Par exemple, supposons que vous achetez deux raquettes de tennis à 50$ et un boîte de balles à 12$, et que vous voulez connaître le coût total de votre achat, qui est sujet à une taxe de 15%. Voici une façon de décomposer le travail en une série d’expressions n’effectuant chacune qu’une seule opération :

coûtRaquettes = 50 * 2
100

coûtAvantTaxe = coûtRaquettes + 12
112

taxe = coûtAvantTaxe * 0.15
16.8

coûtTotal = coûtAvantTaxe + taxe
128.8

Évidemment, nous verrons sous peu qu’il est possible de combiner toutes ces opérations en une seule expression (en utilisant les parenthèses), mais l’exemple illustre un type important d’utilisation des variables.

Modification d’une variable

Si l’on affecte une nouvelle valeur à une variable déjà définie, l’ancienne valeur stockée disparaît; elle est simplement remplacée par la nouvelle valeur :

y = "cerf-volant"
"cerf-volant"

y = 40 + 2
42

y
42

Notons que, dans ce dernier exemple, la seconde assignation a fait passer le type de valeur contenue dans y de caractère à numérique. Le fait que le contenu d’une variable puisse passer librement d’un type à un autre est une des caractéristiques de JS qui en font un langage dynamique. Dans un langage statique, les variables sont créées avec un type donné et toutes les valeurs qu’on y place doivent être de ce type.

Auto-réassignation

Supposons que la variable y soit définie ainsi :

y = 42
42

Un enchaînement d’opérations – ou « pattern » – que l’on retrouve très souvent en programmation est l’auto-réassignation, qui consiste en une assignation où la nouvelle valeur d’une variable est calculée à partir de son ancienne valeur :

y = y + 1    ← auto-réassignation
43    ← nouvelle valeur

y = y + 1    ← auto-réassignation
44    ← nouvelle valeur

y
44    ← valeur après les auto-réassignations

L’effet des auto-réassignations ci-dessus était d’augmenter de 1 la valeur de la variable y. Nous verrons dans le cours que le JS possède certains opérateurs spécifiquement pour effectuer certaines auto-réassignations courantes, comme justement augmenter de 1 la valeur d’une variable numérique.

L’auto-réassignation peut aussi se faire avec une variable caractères :

nom = "Jeanne"
"Jeanne"

nom = nom + " d’Orléans"    ← auto-réassignation
"Jeanne d’Orléans"    ← nouvelle valeur

nom
"Jeanne d’Orléans"    ← valeur après l’auto-réassignation


Enchaînement d’expressions

Comme nous avons dit plus haut, un nom de variable définie est en soi une expression bien formée, dont la valeur est celle stockée dans la variable. Nous avons aussi dit qu’un nom de variable peut remplacer une constante dans une des formes d’expression vues jusqu’ici. Cette règle est un cas particulier d’une règle plus générale, fondamentale en JS (et en programmation en général), permettant de construire des expressions qui expriment de façon très compacte des calculs complexes. C’est la règle d’enchaînement d’expressions. Elle tient en peu de mots, mais ses conséquences sont vastes :

Si une expression bien formée contient une constante, on peut remplacer cette constante par une autre expression bien formée, et ce qu’on obtient est aussi une expression bien formée.

Par exemple, si l’on prend l’expression 40 + 2 et qu’on y remplace 2 par une autre expression, mettons 85/3, on obtient :

40 + 85/3

qui est aussi une expression bien formée. On aurait tout aussi bien pu remplacer le 40 au lieu du 2, et on aurait obtenu :

85/3 + 2

qui est encore une expression bien formée. On aurait aussi pu remplacer le 40 par une autre expression, mettons x = 200 :

x = 200 + 2

La règle d’enchaînement nous dit qu’il s’agit encore d’une expression bien formée.

Un autre exemple est donné en annexe, mais essentiellement, ce qu’il faut retenir, c’est que l’on peut enchaîner autant d’opérations que l’on veut dans une même expression.

Parenthésage

La possibilité d’enchaîner les expressions soulève la question de l’ordre d’exécution des opérations dans une expression qui comporte plusieurs opérateurs. En effet, est-ce que l’expression :

2 + 7 * 5

donne comme résultat 37 ou 45 ? Si on exécute la multiplication d’abord (comme on nous apprend à faire à l’école), elle donne 37, alors que si on effectue l’addition d’abord, elle donne 45. Laquelle des deux possibilités JS choisit-il ?

Un premier élément de réponse vient d’une autre règle importante pour la construction d’expressions, celle du parenthésage. Nous connaissons tous déjà cette règle :

Si on entoure de parenthèses ( ) une expression bien formée, on obtient encore une expression bien formée.

Si, par la règle d’enchaînement, une expression contient une partie parenthésée, cette dernière est évaluée avant la ou les opérations qui jouxtent les parenthèses. Ainsi, on peut imposer un ordre d’exécution en utilisant des parenthèses. On obtiendrait donc l’une des deux expressions suivantes :

(2 + 7) * 5

qui donne sans équivoque possible le résultat 45, et :

2 + (7 * 5)

qui donne sans plus d’équivoque le résultat 37.

Les parenthèses permettent donc d’imposer un ordre d’évaluation aux expressions composées en vertu de la règle d’enchaînement. Il n’y a aucune limite sur la « profondeur » avec laquelle on peut parenthéser les expressions.

Priorité des opérateurs

Puisqu’on peut imposer l’ordre d’exécution des opérations dans une expression en utilisant des parenthèses, on peut faire du JS toute sa vie sans jamais se préoccuper de la priorité des différents opérateurs l’un par rapport à l’autre. Cependant, on peut parfois éviter d’utiliser les parenthèses en exploitant le fait que JS attribue à chaque opérateur une priorité, dont il se sert pour déterminer l’ordre d’exécution des opérations dans une expression complexe en l’absence de parenthèses.

Par exemple, les opérateurs * et / ont une priorité supérieure à celle des opérateurs + et -, ce qui correspond aux règles d’arithmétique usuelles.

Ainsi, on peut se permettre d’écrire :

2 + 7 * 5

au lieu de :

2 + (7 * 5)

(si on veut effectivement que la multiplication s’effectue avant l’addition) puisque de toute façon le * a plus haute priorité que le +.

Les règles complètes concernant la priorité des opérateurs sont :

  1. Les opérateurs de plus haute priorité sont exécutés avant ceux de plus basse priorité.
  2. En l’absence de parenthèses, les opérateurs d’égale priorité sont exécutés de gauche à droite.

Ainsi, dans l’expression :

12 - 7 + 5

la soustraction est effectuée avant l’addition, puisque + et - sont effectuées de gauche à droite, ayant la même priorité. Le résultat est donc 10, et non 0, qui serait le résultat de :

12 - (7 + 5)

La table en pp. 661-2 de McPeak&Wilton (tout comme la Table 22-10 en pp. 434-5 de Goodman et al.) donne toute l’information sur la priorité relative des opérateurs JS.

Même si connaître la priorité de tous les opérateurs JS peut nous éviter de mettre des parenthèses inutiles dans une expression, ce n’est absolument pas nécessaire. En cas de doute sur la priorité relative de deux opérateurs, on peut simplement décider d’utiliser des parenthèses, quitte à ce qu’elles soient redondantes. Une paire de parenthèses de trop ne fait jamais de tort et peut même parfois augmenter la lisibilité d’une expression !

Cela étant dit, en connaître un minimum sur la priorité des opérateurs JS s’avère extrêmement utile. Dans ce cours, les trois règles suivantes constituent un minimum suffisant :

À savoir concernant la priorité des opérateurs

  1. Comme en arithmétique élémentaire, les opérateurs * et / ont la même priorité, laquelle est supérieure à celle des opérateurs + et -, qui sont aussi entre eux d’égale priorité.
  2. L’opérateur d’assignation "=" a la plus basse priorité.
  3. L’opérateur "." (accès à un membre), que nous verrons sous peu, a la plus haute priorité.

Ainsi :

v = 12 - 7 * 5
-23

est interprété comme :

v = (12 - (7 * 5))

et non comme :

v = ((12 - 7) * 5)
25

ni comme :

(v = 12) - (7 * 5)
-23

qui affiche pourtant le même résultat, mais qui n’a pas le même effet. Pour bien comprendre ce que fait cette dernière expression, il faut se rappeler que l’assignation, en tant qu’expression, retourne comme résultat la valeur tout juste assignée. L’expression placerait donc la valeur 12 dans v et retournerait -23 comme résultat, alors que l’expression originelle place -23 comme valeur dans v, en plus de retourner cette même valeur (-23) comme résultat.

Tel que mentionné plus tôt, il n’y a aucune limite sur la profondeur avec laquelle on peut enchaîner et parenthéser les expressions. En pratique, la limite est plutôt la lisibilité de l’expression résultante. Cela étant dit, une expression d’une certaine complexité peut par ailleurs demeurer très lisible.

Reprenons l’exemple ci-dessus de l’achat de deux raquettes de tennis à 50$ et d’un boîte de balles à 12$, où l’on veut connaître le coût total de l’achat, qui est sujet à une taxe de 15%. Le coût total peut facilement être calculé par une expression unique :

coûtTotal = (2 * 50 + 12) + (2 * 50 + 12) * 0.15
128.8

que l’on peut même simplifier (si l’on pense à la mise en évidence simple) :

coûtTotal = (2 * 50 + 12) * 1.15
128.79999999999998

Belle occasion de noter que, en JS comme partout en informatique, les calculs numériques sont effectués avec une précision limitée et que des erreurs d’arrondi peuvent toujours survenir, comme le démontre l’évaluation de l’expression précédente. JS possède tout ce qu’il faut pour bien traiter ces cas, par exemple en arrondissant le résultat d’une opération à deux chiffres après le point (en utilisant par exemple Math.round() ou .toFixed()), mais ce sujet dépasse la portée du présent texte.

Sous-expressions et LHS

Une expression imbriquée dans une autre expression plus longue est appelée sous-expression si l’ordre d’exécution des opérations fait en sorte que toutes les opérations dans l’expression imbriquée sont effectuées avant la ou les opérations qui la jouxtent dans l’expression plus longue. Par exemple, dans :

12 - 7 * 5
-23

l’expression 7 * 5 est une sous-expression, mais pas 12 - 7.

Techniquement, 12, 7 et 5 sont aussi toutes les trois des sous-expressions, puisque (1) il s’agit bel et bien d’expressions (rappelez-vous qu’une constante est en elle-même une expression) et (2) ne contenant aucune opération, on peut dire que « toutes » les opérations contenues dans l’expression sont effectuées avant celle(s) située(s) à gauche et/ou à droite de l’expression.

Les sous-expressions de :

prixTotal = prix / 2 + 50

sont :

prixTotal
prix
2
50
prix / 2
prix / 2 + 50

Le cas de prixTotal demande explications : comme elle est située à gauche d’un opérateur d’assignation "=", elle est évaluée simplement comme nom de variable, c’est-à-dire comme « endroit où placer la valeur de l’expression située à droite du "=" ». En ce sens, elle est évaluée entièrement avant le "=" lui-même.

Techniquement, une sous-expression située à gauche d’un opérateur "=" est appelée « partie de gauche », ou en anglais « left-hand side » (LHS). Nous verrons plus tard qu’une LHS n’est pas nécessairement un simple nom de variable, mais peut être une sous-expression plus complexe. Mais, peu importe sa complexité, une LHS a toujours la même fonction : indiquer un emplacement où stocker la valeur JS qui est à droite du "=".

Arbres d’exécution

Nous verrons en classe un outil graphique permettant d’analyser des expressions complexes et de mettre en évidence l’ordre d’exécution des opérations : les arbres d’exécution.


Autres opérations

Nous allons maintenant étendre un peu notre répertoire d’opérations JS. Plusieurs autres opérations s’ajouteront aussi en classe.

Comparaisons, valeurs booléennes

Deux des valeurs autonymes mentionnées au début de ce texte sont les valeurs booléennes : true et false, représentées dans les expressions par les constantes de même nom :

true
true

false
false

Plusieurs opérations JS retournent comme résultat une valeur booléenne. C’est le cas notamment des opérations de comparaison, qui servent à comparer deux valeurs JS.

Égalité (==)

La plus simple des opérations de comparaison est celle d’égalité, représentée par l’opérateur == (deux caractères « = », à ne pas confondre avec l’assignation, qui en utilise un seul). L’opération d’égalité vérifie simplement si ses deux arguments sont égaux, et retourne true (vrai) si c’est le cas, et false (faux) autrement. Rappelons qu’un argument en JS est toujours une unique valeur JS. Voici des exemples d’opération d’égalité :

42 == 42
true

42 == (15 + 27)
true

La priorité de == est inférieure à celle des opérations arithmétiques; les parenthèses ne sont donc pas nécessaires :

42 == 15 + 27
true

"abc" == 'abc'
true

'a' == 'a '
false

"a" == "A"
false

"a" == ('a' + "")
true

true == true
true

true == false
false

true == (40 == 40+2)
false

Autres opérations de comparaison

Les autres opérations de comparaison incluent :

Autres opérateurs de comparaison
Opérateur Opération
!= N’est pas égal à
> Est plus grand que
>= Est plus grand que ou égal à
< Est plus petit que
<= Est plus petit que ou égal à

Toutes ces opérations, à l’instar de l’égalité ==, peuvent travailler avec des valeurs numériques, caractères et booléennes. Avec des valeurs caractères, la comparaison s’effectue caractère par caractère et respecte la numérotation Unicode des caractères. Les valeurs booléennes true et false sont traitées comme les valeurs numériques 1 et 0, respectivement.

Voici quelques exemples :

42 >= 42
true

42 > 42
false

-10 <= 0
true

"A" > 'a'
false

"A" < 'a'
true

"a " > 'a'
true

100 != 100.000
false

true != false
true

true > false
true

Ce dernier exemple équivaut à écrire : 1 > 0, d’où le résultat obtenu.

Les valeurs booléennes true et false sont aussi traitées comme 1 et 0 par les opérateurs arithmétiques :

true+true
2

43-(4==2+2)
42

42*("a"=="A")
0

Il y a peu d’intérêt à écrire et faire exécuter des comparaisons qui n’impliquent que des constantes, puisqu’on peut très bien effectuer la comparaison mentalement et connaître le résultat avant même de les faire exécuter. Le seul intérêt possible est si l’on veut vérifier le fonctionnement exact de ces opérations.

En général, donc, les comparaisons surviendront dans le cours d’un script, où elles seront appliquées à des variables dont on ne connaît pas déjà la valeur au moment de la rédaction du script. Par exemple, un script pourrait d’abord demander à l’utilisatrice de fournir un montant d’argent, qui serait stocké dans la variable montant, puis ensuite effectuer la comparaison suivante :

cher = montant > 1000

Notons qu’au moment de rédiger le script, on ne peut pas savoir quelle sera le résultat de la comparaison, et donc quelle valeur sera stockée dans cher. La valeur (true ou false) dépendra de la valeur contenue dans montant au moment de l’exécution, ce qui fait tout l’intérêt de l’énoncé.

Opérateurs booléens

Les opérations booléennes bien connues OU, ET et NON sont réalisées respectivement par les opérateurs ||, && et !. Les deux premiers sont des opérateurs binaires, signifiant qu’à l’instar des opérateurs arithmétiques usuels (+, -, * et / ), ils s’utilisent avec deux arguments : un à gauche et un à droite. Le troisième (!) est unaire, et s’utilise avec un seul argument, qui s’inscrit à droite de l’opérateur.

Les trois opérateurs booléens prennent en argument, et retournent, des valeurs booléennes, soit true ou false :

false || true
true

true && false
false

!true
false

Les opérateurs booléens permettent de formuler des conditions complexes, ce qui deviendra utile sous peu, pour exprimer des calculs conditionnels. Notamment, ils permettent d’exprimer des critères complexes en combinant des comparaisons. Par exemple, en supposant que la variable montant contienne un montant d’argent, l’expression suivante permet de vérifier que ce montant est situé entre 1 et 1000 :

montant >= 1 && montant <= 1000

La priorité des opérateurs booléens est plus basse que celle des comparaisons, alors les parenthèses ne sont pas nécessaires ici. En cas de doute, bien sûr, on peut y aller avec la ceinture et les bretelles :

(montant >= 1) && (montant <= 1000)

Au contraire, l’expression suivante vérifie que le montant n’est pas situé entre 1 et 1000 :

!(montant >= 1 && montant <= 1000)

Ici, les parenthèses sont requises car le NON (!) doit s’appliquer au résultat du ET (&&).

Le choix conditionnel « ? : »

Voici une opération très utile qui permet d’effectuer un « calcul » conditionnel de manière très simple : le choix conditionnel.

Contrairement aux opérations arithmétiques de base (+, -, ×, ÷), qui travaillent toutes sur deux valeurs, le choix conditionnel travaille sur trois valeurs. Pour cette raison, elle est représentée en JS par un opérateur un peu spécial, ? :, constitué de deux symboles distincts, entre lesquels va s’insérer la seconde des trois valeurs à traiter (un peu comme le ne pas en français, qui peut se séparer en deux pour accueillir d’autres mots : Jean ne viendra pas dîner).

Une expression qui utilise l’opérateur de choix conditionnel ? : s’appelle une expression conditionnelle.

L’utilisation typique du choix conditionnel utilise une comparaison comme premier argument :

(comparaison) ? valeur-si-vrai : valeur-si-faux

comparaison est une opération de comparaison, valeur-si-vrai est la valeur à retourner si le résultat de la comparaison est true, et valeur-si-faux est la valeur à retourner si le résultat de comparaison est false.

Quelques exemples devraient suffire à clarifier le fonctionnement du choix conditionnel. Pour tester ces exemples, définissez d’abord les variables sexe, nombre et montant en faisant exécuter une et une seule expression, à votre choix, parmi chacun des trois groupes suivants :

Groupe 1
sexe = "F"
sexe = "M"
Groupe 2
nombre = 0
nombre = 1
Groupe 3
montant = 10
montant = 100

Faites maintenant exécuter, une par une, les expressions conditionnelles suivantes :

  (sexe == "F") ? "Madame" : "Monsieur"
  "Bonjour " + ((sexe == "F") ? "Madame" : "Monsieur")
  (nombre > 0) ? "Vous avez du courrier" : "Pas de courrier"
  (montant < 50) ? "Pas très cher…" : "Plutôt cher !"

Les résultats obtenus varieront en fonction de la valeur des variables sexe, nombre et montant, donc en fonction des choix que vous avez faits ci-dessus.

La valeur qui vient avant le ? est le premier argument de l’opérateur ? :, celle qui vient entre le ? et le : en est le deuxième argument, et celle qui vient après le : le troisième. Il est important de bien repérer les sous-expressions qui correspondent à chacun des trois arguments dans un choix conditionnel :

La forme générale du choix conditionnel est comme suit :

valeur-booléenne ? valeur-si-vrai : valeur-si-faux

En principe, le premier argument pourrait être une constante, true ou false :

true ? 800 : 1000
800

false ? 800 : 1000
1000

Comme avec les opérateurs de comparaison, il y a peu d’intérêt à écrire une expression conditionnelle si on connaît déjà la valeur du premier argument au moment de la rédiger. C’est la raison pour laquelle le premier argument est presque toujours une variable ou une comparaison faisant intervenir une variable dont on ne connaît pas la valeur au moment où on rédige l’expression.

Ce qu’il faut comprendre, c’est qu’au moment où l’expression sera exécutée dans le cours du script où elle figure, la variable aura bel et bien une valeur déterminée, et l’interprète JS pourra ainsi déterminer s’il doit retourner comme résultat du choix conditionnel le deuxième argument ou plutôt le troisième.

- et + unaires

L’opérateur "-" peut s’utiliser avec un seul argument, numérique, à droite; il sert alors à inverser le signe de la valeur numérique :

-42
-42

-(-42)
42

- - 42
42

L’opérateur "+" peut aussi s’utiliser de façon unaire, mais comme il ne modifie pas la valeur numérique, sa présence ne change rien :

+42
42

Ces opérateurs unaires peuvent aussi s’utiliser avec une valeur caractère, à condition qu’elle puisse être convertie en nombre. La valeur est d’abord convertie en valeur numérique, puis l’opérateur est appliqué :

+"42"
42

-"42"
-42

+ " -42 "
-42

Le "+" unaire est donc une façon simple de convertir une valeur caractère en valeur numérique, pourvu que la valeur caractère représente bien un nombre.

Si la valeur caractère ne représente pas un nombre, on obtient la valeur autonyme NaN (pour Not a Number) :

+"1.2.3"
NaN

-"abc"
NaN


Opérations à syntaxe particulière

Syntaxiquement, les opérations suivantes s’expriment non pas à l’aide de symboles (comme +, -, *, / ou ? :), mais à l’aide d’éléments syntaxiques propres aux objets et aux fonctions, qui sont un type d’objets. Pour le moment, il faut simplement accepter qu’elles s’expriment avec cette syntaxe, qui sera démythifiée plus tard.

Dans cette syntaxe, chaque opération est identifiée par un nom, semblable à un nom de variable, mais pouvant comporter un ou des ".". Également, les valeurs à traiter – appelées arguments ou paramètres – doivent être données entre parenthèses après le nom de l’opération, séparées l’une de l’autre par une virgule. Parfois aussi, une des valeurs à traiter doit être donnée avant le nom de l’opération.

Opérations mathématiques

Les opérations suivantes servent à trouver respectivement le minimum et le maximum parmi des valeurs numériques. Leurs noms sont Math.min et Math.max, mais nous allons dès maintenant adopter la convention de notation, qui vient du monde des objets, consistant à faire suivre le nom d’une fonction de parenthèses vides (), comme rappel du fait qu’il s’agit d’une fonction. Nous les appelons donc :

Math.min() et Math.max()

Tel que mentionné plus haut, pour utiliser ces fonctions, on met les valeurs à traiter en arguments, entre les parenthèses, séparées l’une de l’autre par des virgules :

Math.min(15, 10)
10

Dans l’évaluation des arguments, chacun d’eux est évalué séparément comme une sous-expression, de gauche à droite :

Math.min(3 + 2, 4)
4

Math.max(3 + 2, 4)
5

Math.max(Math.min(5, 2), 4)
4

Tout comme avec le choix conditionnel (? :) tout à l’heure, il y a peu d’intérêt à calculer le maximum ou le minimum parmi un ensemble de valeurs constantes, que l’on connaît déjà. C’est donc dans le contexte d’un script contenant plusieurs énoncés, et en travaillant avec des variables dont la valeur est inconnue au moment de la rédaction du script, que ces fonctions revêtent un intérêt.

Math.max() et Math.min() peuvent s’utiliser avec plus de deux valeurs, par exemple :

Math.max(-12, 18, 4)
18

Il existe plusieurs autres fonctions mathématiques qui utilisent cette syntaxe particulière. Mentionnons à titre d’exemples, la racine carrée Math.sqrt() (pour square root), à un seul argument :

Math.sqrt(49)
7

et l’exposant, Math.pow() (pour power), à deux arguments :

Math.pow(5, 3)
125

Opérations sur les chaînes de caractères

Les opérations suivantes travaillent sur les chaînes de caractères. Elles s’expriment en ajoutant le nom de l’opération après la valeur caractère. Par exemple :

.length
Retourne la longueur de la chaîne, c’est-à-dire le nombre de caractères qu’elle contient :

"joselito".length
8

Il faut s’habituer à cette syntaxe particulière, qui est déroutante au premier abord, puisque l’opération vient après la valeur sur laquelle elle s’applique. Comme les fonctions Math.max(), Math.min(), etc., ces opérations sur les valeurs caractères utilisent une syntaxe propre aux objets.

Elles héritent de cette syntaxe leur très haute priorité, la plus haute de tous les opérateurs JS.

La chaîne sur laquelle s’applique l’opération est appelée le sujet de l’opération (encore une analogie liée à la langue naturelle !). Dans l’exemple ci-dessus, la chaîne sujet, soumise à l’opération .length, est "joselito".

La chaîne sujet n’est pas nécessairement une constante, elle peut être n’importe quelle valeur caractère, tel que l’illustre l’exemple suivant :

("Bonjour " + 'vous').length
12

Notons que les parenthèses sont ici nécessaires. Sans elles :

"Bonjour " + 'vous'.length

le .length serait appliqué au 'vous' seulement (à cause de la priorité du .length supérieure à celle du +), ce qui aurait été équivalent à :

"Bonjour " + 4

ce qui, par conversion automatique, donnerait comme résultat :

"Bonjour 4"

… pas le résultat que nous escomptions.

Éventuellement, si l’opération nécessite d’autres valeurs que la chaîne sujet elle-même, celles-ci sont données en arguments entre parenthèses après le nom de l’opération, séparées l’une de l’autre par une virgule s’il y a plus d’une, comme pour Math.max() et Math.min() :

.charAt()
Extrait un caractère à une position spécifique dans la chaîne sujet; la position (numérique) est donnée en argument :

"joselito".charAt(2)
"s"

"joselito".charAt(0)
"j"

Comme on peut constater, les positions sont numérotées à partir de zéro (0). L’opération peut aussi s’utiliser sans argument, dans quel cas elle retourne le premier caractère (celui en position 0) de la chaîne sujet :

"joselito".charAt()
"j"

Que se passe-t-il si la position passée en argument est ≥ la longueur de la chaîne sujet ? Essayez-le !
.slice()
Extrait une sous-chaîne située entre deux positions spécifiques données en arguments :

"joselito".slice(2, 5)
"sel"

Le caractère en position finale est exclu de la sous-chaîne retournée. Si le second argument est omis, tout le reste de la chaîne est retourné :

"joselito".slice(2)
"selito"

.toUpperCase()
Transforme en majuscules les lettres minuscules présentes dans la chaîne sujet; elle n’a besoin d’aucun argument (mais il faut quand même inscrire les parenthèses) :

"joselito".toUpperCase()
"JOSELITO"

Les caractères qui ne sont pas des lettres minuscules restent inchangés :

"23 décembre".toUpperCase()
"23 DÉCEMBRE"

.toLowerCase()
Transforme en minuscules les lettres majuscules présentes dans la chaîne :

"Joyeux Événements".toLowerCase()
"joyeux événements"

Les caractères qui ne sont pas des lettres majuscules restent inchangés.
.indexOf()
Recherche, dans la chaîne sujet, la position de la première occurrence de la chaîne passée en argument :

"paradoxal".indexOf("a")
1

"paradoxal".indexOf("al")
7

La valeur retournée est une valeur numérique. Si la chaîne recherchée ne se trouve nulle part dans la chaîne sujet, la valeur -1 est retournée :

"paradoxal".indexOf("oxyde")
-1

Que se passe-t-il si la chaîne recherchée est vide ("") ? Essayez-le !
.includes()
Prend en argument une chaîne à rechercher dans la chaîne sujet. Retourne une valeur booléenne : true si la chaîne recherchée se trouve quelque part dans la chaîne sujet et false si elle ne s’y trouve pas :

"paradoxal".includes("al")
true

"paradoxal".includes("oxyde")
false

On notera que ch1.includes(ch2) retourne false si et seulement si ch1.indexOf(ch2) == -1.

Bien sûr, par la règle d’enchaînement, ces opérations peuvent être combinées entre elles et/ou être utilisées comme sous-expressions dans d’autres expressions :

"joselito".slice(2, 5).toUpperCase()
"SEL"

Math.max("joselito".length * 2, 15)
16

Interactions de base avec l’utilisatrice

Les fonctions suivantes permettent de « dialoguer » avec l’utilisatrice dans la fenêtre de navigation (et non à la console). Contrairement aux fonctions vues jusqu’ici, elles ne font pas intrinsèquement partie du JS, mais ne sont disponibles qu’en environnement navigateur Web.

prompt()
Affiche, dans la fenêtre de navigation, la chaîne passée en argument, suivie d’une boîte de saisie, dans laquelle l’utilisatrice est invitée à saisir quelque chose. La fonction retourne comme valeur la suite de caractères qui ont été saisis par l’utilisatrice. Par exemple :

prompt("Entrez votre nom SVP")

fait afficher la boîte suivante dans la fenêtre de navigation :

prompt.png

Supposons que l’utilisatrice tape « Léa » puis clique sur OK, la fonction retournera comme résultat à la console :

"Léa"     ← Dépend de ce que l’utilisatrice a saisi

Essayez-le vous-même, en inscrivant ce que vous voulez dans la boîte de saisie.

Si l’utilisatrice clique sur Annuler au lieu de OK, la fonction retourne la valeur autonyme null.

Évidemment, si on prend la peine de demander une information à l’utilisatrice, c’est qu’on voudra en faire quelque chose. Pour cette raison, le résultat de prompt() est presque toujours stocké dans une variable, par exemple :

nom = prompt("Entrez votre nom SVP")

alert()
La fonction alert() permet d’afficher dans la fenêtre de navigation une valeur caractère, typiquement un message à l’intention de l’utilisatrice. Elle n’attend rien de la part de l’utilisatrice, sinon que de cliquer OK pour confirmer qu’elle a bien vu le message à son intention :

alert("Bonjour le monde !")

fait afficher la boîte suivante dans la fenêtre de navigation :

alert.png

alert() peut aussi s’utiliser avec une valeur numérique :

alert(12/13)

fait afficher ceci dans la fenêtre de navigation :

alert2.png

Comme toute fonction en JS, alert() doit retourner une valeur, qui représente le « résultat » du traitement effectué par la fonction (tout comme la somme des deux arguments est le résultat retourné par +). Ici, cependant, l’intérêt de la fonction ne réside pas dans ce qu’elle « calcule », mais bien dans ce qu’elle fait. Il n’y a donc naturellement aucun résultat intéressant qu’elle pourrait retourner. Mais, comme elle doit malgré tout retourner un résultat, les conceptrices de l’environnement Web JS ont décidé (arbitrairement) que la fonction retournerait toujours la valeur autonyme undefined.

Pour cette raison, une fois que l’utilisatrice clique sur OK, l’exécution de la fonction se termine à la console, et on voit apparaître son résultat : undefined. Le dialogue, du point de vue de la console, est donc comme suit :

alert("Bonjour le monde !")
undefined

La fonction prompt(), en faisant intervenir l’utilisatrice dans le « déroulement de l’action », permet d’introduire un peu d’imprévu dans l’exécution des énoncés. En processus d’apprentissage, c’est une excellente façon de mettre en évidence l’importance de la succession des énoncés dans un script.

La succession des trois énoncés suivants illustre bien l’importance de comment les énoncés se suivent, « bâtissant » chacun sur ce que les énoncés précédents ont accompli :

nom = prompt("Entrez votre nom SVP");
réponse =
    nom == "Léa" ?
    "Salut, ma sœur !" :
    "Bonjour " + nom + ".";
alert(réponse);

On note que, pour une question de lisibilité, le deuxième énoncé (celui qui commence par réponse =) a été divisé en quatre lignes.

Pour essayer ce « dialogue » à la console, vous pouvez copier-coller toutes les lignes d’un coup; les trois énoncés seront exécutés l’un après l’autre.

Le genre de dialogue réalisé avec prompt() et alert() est très rudimentaire et nous verrons dans les cours d’autres façons, plus conviviales, d’interagir avec l’utilisatrice.


Environnement, membres

Considérons une expression comme :

prix

Ce qu’on obtient comme résultat de cette expression dépend évidemment des énoncés qui ont été exécutés précédemment. Si la variable n’a jamais été définie, on obtiendra un message d’erreur, par exemple :

Uncaught ReferenceError: prix is not defined

Si, au contraire, la variable a été définie, on obtiendra comme résultat la valeur qui y est couramment stockée. Cette valeur dépend bien sûr de l’assignation qui a donné sa dernière valeur à la variable.

Pour pouvoir évaluer les expressions en tenant compte des énoncés passés, JS garde en permanence une trace de quelles variables sont définies et de la valeur de chacune. Cette trace est conservée en mémoire, par l’interprète JS, dans ce qu’on appelle l’environnement d’exécution, ou simplement l’environnement.

En première approximation, on peut considérer l’environnement comme une commode à tiroirs, dont certains portent un nom. Chaque tiroir peut contenir une (et exactement une) valeur JS, c’est-à-dire une valeur simple (numérique, caractère ou autonyme) ou un pointeur à un objet :

termino1N.png
termino2N.png
termino3N.png
termino4N.png

À chaque variable correspond un tiroir de l’environnement, mais certains tiroirs ne correspondent pas à une variable définie par assignation; nous y reviendrons sous peu (nous ne les avons pas inclus dans notre exemple). Pour cette raison, les tiroirs de l’environnement s’appellent membre de l’environnement, et non « variable ». L’environnement hypothétique ci-dessus pourrait résulter, par exemple de la suite des trois assignations suivantes :

maVar1 = 459
maVar2 = "Québec"
maVar3 = "Montréal"

Les trois premiers membres de l’environnement dans notre exemple correspondraient aux variables maVar1, maVar2 et maVar3.

Comme pour les variables, deux membres ne peuvent pas porter le même nom et le nom d’un membre constitue en lui-même une expression JS bien formée, dont le résultat est la valeur JS contenue dans le membre. Comme pour les variables, il n’y a pas de limite sur le nombre de membres qu’il peut y avoir dans l’environnement.

Membres statutaires

Quels sont donc les membres de l’environnement qui ne sont pas des variables ? Chaque type d’environnement où du JS peut s’exécuter possède des membres statutaires, c’est-à-dire des membres qui existent dans l’environnement avant même que ne s’exécute le premier énoncé d’un programme ou que l’on n’ouvre la console JS. Ces membres sont dits statutaires; ils sont dans l’environnement dès sa création, ils ne sont pas créés par un énoncé d’assignation. Les membres statutaires sont très importants, certains sont aussi utiles que les opérations de base du JS comme +, -, * et /.

Le type d’environnement qui nous intéresse, l’environnement « navigateur Web », ne fait pas exception. Avant même que ne s’exécute le premier énoncé d’une page Web ou que ne début une session à la console JS, l’environnement contient un grand nombre de membres statutaires, chacun stockant une valeur JS. Rappelons que les membres statutaires n’étaient pas montrés dans l’exemple d’environnement ci-dessus.

Un des membres statutaires de l’environnement navigateur Web est innerWidth. On peut donc formuler à la console JS l’énoncé suivant, même si on n’a jamais assigné de valeur à « innerWidth » :

innerWidth
1600

Le membre innerWidth contient donc la valeur numérique 1600. La réponse que vous obtenez pourrait être différente, puisqu’elle dépend de réglages spécifiques dans votre navigateur.

Un autre membre statutaire de l’environnement navigateur Web est name. Vous pouvez connaître la valeur qu’il contient en tapant son nom dans la console JS :

name
""

La valeur contenue dans name est donc de type caractère et il s’agit de la chaîne vide.

Les membres statutaires ne sont pas des variables, et la plupart ne peuvent pas être modifiés. Par exemple, closed est dans ce cas :

closed
false

(false est une des valeurs autonymes évoquées plus tôt). Si on essaie de modifier la valeur de closed :

closed = 'essai'
"essai"

L’assignation semble avoir réussi, mais si on redemande la valeur de closed :

closed
false

force est de constater que la valeur n’a pas changé.

Les navigateurs modernes comptent plus de 200 membres statutaires. C’est la raison pour laquelle nous ne les avions pas inclus dans l’exemple d’environnement donné ci-dessus.


Objets

Poursuivons notre exploration de l’environnement navigateur Web, dont un autre membre statutaire est Math :

Math
▸Math { … }

La puce "▸" au début de la réponse obtenue indique que la valeur de Math est un pointeur à un objet. Structurellement, un objet est similaire à l’environnement, c’est-à-dire analogue à un ensemble de « tiroirs » étiquetés, chacun contenant exactement une valeur JS. Ces « tiroirs » s’appellent aussi « membres », comme ceux de l’environnement. Le mot qui suit la puce indique le type de l’objet pointé. Ici, le type de l’objet pointé est identique au nom du membre de l’environnement, mais ce n’est pas toujours le cas.

Quelque part dans la mémoire de l’interprète JS, il y a donc un objet de type Math, que l’on pourrait représenter ainsi :

termino22.png

Notons que cet objet n’est pas dans le tiroir Math de l’environnement; en effet, un objet n’est pas une valeur JS, et un tiroir ne peut contenir que une valeur JS :

termino5.png

Ce qui se trouve dans le tiroir Math est un pointeur à l’objet. Un pointeur est une « adresse » interne à l’interprète JS, que celui-ci peut utiliser pour accéder à l’objet en mémoire. La façon de représenter la relation entre l’environnement et l’objet auquel Math pointe est celle-ci :

termino23N.png

Nous avons inscrit "#678" à titre illustratif comme contenu du tiroir Math, mais en fait, JS n’affiche jamais directement la valeur interne d’un pointeur à un objet (ce ne serait d’ailleurs d’aucune utilité); il nous montre plutôt, comme nous avons vu, la puce "▸" suivie du type de l’objet pointé. L’important est que, pour l’interprète JS, le contenu du tiroir permet d’accéder à l’objet pointé.

Un pointeur à un objet est une valeur JS et, à ce titre, on peut le mettre dans une variable. Ainsi, on pourrait faire cette assignation :

monMath = Math
▸Math { … }

Nous nous retrouverions donc avec deux membres de l’environnement pointant au même objet, ce qui est tout à fait possible :

termino25N.png

Deux des opérateurs de comparaison que l’on connaît déjà pour les valeurs numériques et caractères peuvent être utilisés pour comparer des pointeurs : == et !=. Si la comparaison avec == donne true (dans quel cas celle avec != donnera false), c’est qu’ils pointent au même objet :

monMath == Math
true

monMath != Math
false

Abus de langage utile et répandu

Un objet n’est pas une valeur JS. Seul un pointeur à un objet est une valeur JS, qui peut être mise dans une variable et traitée par les différents opérateurs JS. Cependant, il arrive très fréquemment (y compris dans les livres de JS et dans le présent texte) que l’on parle d’un pointeur à un objet comme s’il s’agissait de l’objet lui-même. Ainsi, par exemple, au lieu de dire que Math pointe à un objet de type Math, on dira habituellement que « Math est un objet de type Math ».

Ce genre d’abus de langage ne cause en général pas de confusion. Il faut cependant toujours garder à l’esprit qu’un objet n’est jamais lui-même stocké dans une variable, ni passé en argument à un opérateur, ni retourné comme résultat d’une expression.

Digression : Exploration d’un objet dans la console

Dans l’affichage que la console JS fait d’un pointeur à un objet, si on clique sur la puce "▸" qui précède le type d’objet, l’affichage se « déplie » en un aperçu de l’objet pointé : une liste alphabétique des noms de membres présents dans l’objet, chacun suivi de sa valeur. Pour le membre Math de l’environnement, l’affichage obtenu après dépliage commence ainsi :

termino20.png

Parmi les membres visibles dans l’image, on remarque que certains sont eux-mêmes précédés de la puce "▸". Les membres abs, acos, acosh, par exemple, sont dans ce cas. Ces membres sont eux-mêmes des pointeurs à des objets (dans notre métaphore des commodes, chacun de ces objets pointés est une commode quelque part dans la mémoire de l’interprète JS). Ces membres peuvent aussi être « dépliés », récursivement, en cliquant sur la puce. Par exemple, si on « déplie » abs, on obtient :

termino24.png

Il est possible, de cette façon, d’explorer un objet pointé par un membre de l’environnement dont on connaît le nom. Notons qu’on peut explorer l’environnement lui-même par le truchement du membre statutaire globalThis, qui contient un pointeur à l’environnement lui-même ! Si vous le faites avec Firefox, notez que la plupart des membres de globalThis (donc, de l’environnement) sont regroupés sous l’entrée « ▸<default properties> » (Chrome et Edge les affichent normalement).

Opérateur « . », chemins d’accès

L’environnement est lui-même un objet, avec un statut particulier : c’est le seul objet dont les membres peuvent être nommés directement dans une expression JS. Les membres des autres objets ne peuvent pas être nommés directement dans une expression JS. Ainsi, bien que l’objet Math possède un membre PI, on ne peut pas en voir la valeur en tapant son nom directement à la console :

PI
Uncaught ReferenceError: PI is not defined

L’opérateur « . », aussi appelé accès à un membre ou opérateur point (“dot operator”), vient ici à la rescousse et permet d’accéder indirectement au membre en question :

Math.PI
3.141592653589793

On reconnaît bien sûr, d’une part, la célèbre constante mathématique π et, d’autre part, l’expression Math.PI, vue précédemment. En tant qu’expression, Math.PI est l’application de l’opérateur « . » à l’objet Math et au nom de membre PI.

Comme il a été dit précédemment, l’opérateur « . » a une priorité plus haute que celle de n’importe quel autre opérateur. Il prend à gauche un pointeur à un objet et à droite le nom du membre à interroger. L’opération retourne la valeur JS contenue dans le membre interrogé.

Nous verrons plus loin que l’opérateur "." peut s’utiliser avec une valeur simple à gauche. C’est l’opérateur "." que l’on retrouve dans la syntaxe particulière de certaines opérations vues précédemment.

Peu importe son argument de gauche, l’argument de droite de l’opérateur point est toujours un unique nom de membre. D’ailleurs, le nom de membre peut être séparé du "." par des espaces, mais il ne peut pas être mis entre parenthèses. La meilleure pratique est de toujours coller le nom du membre sur le point.

Auto-complétion dans la console

Si vous avez copié-collé l’expression Math.PI dans la console, nous vous invitons à retourner dans la console et à taper vous-mêmes seulement les trois caractères Mat. Vous verrez apparaître ce qu’on appelle une « fenêtre d’auto-complétion ». L’auto-complétion est une fonctionnalité très répandue des outils de programmation, qui suggère à l’utilisatrice différentes façons possibles de compléter ce qu’elle est en train de taper. Dans votre cas, les deux continuations proposées dans la fenêtre d’auto-complétion sont Math et MathMLElement. Pourquoi ces deux propositions ? Parce que ce sont les deux membres de l’environnement dont le nom commence par Mat.

Avec la souris, ou avec les touches ↑ et ↓ suivies de Entrée ou Tab, on peut choisir la continuation voulue dans la fenêtre d’auto-complétion. On peut aussi ignorer les suggestions et simplement continuer à taper. Pour le moment, choisissez la continuation Math. Ce sera exactement comme si vous veniez de taper vous-même Math.

Appuyez maintenant sur la touche ".". Comme le "." est l’opérateur d’accès à un membre, une nouvelle fenêtre d’auto-complétion s’ouvre, proposant comme continuations possibles tous les membres de l’objet Math. Vous n’avez qu’à y piger le nom de membre voulu, par exemple PI. L’expression inscrite à la console devient Math.PI, comme si vous l’aviez tapée en entier vous-même. Vous pouvez alors faire Entrée, comme d’habitude, pour la faire exécuter.

L’auto-complétion fonctionne non seulement avec les membres statutaires, mais également avec les variables définies par la programmeuse.

Chemin d’accès à un membre

Il arrive souvent que plusieurs noms de membre, séparés par des opérateurs point, soient « enfilés » à droite d’un pointeur à un objet, formant ainsi une sorte de « chemin d’accès » menant au membre le plus à droite dans la chaîne.

Prenons un exemple : En environnement navigateur Web, l’environnement possède un membre (statutaire) document :

document
▸HTMLDocument …

Ce membre est un pointeur à un objet qui, à son tour, possède un membre nommé body. Ce membre peut donc être désigné par l’expression :

document.body
▸<body>

Le membre document.body est aussi un pointeur à un objet, lequel contient un membre appelé style, qui peut donc être désigné par l’expression :

document.body.style
▸CSS2Properties(0)

À son tour, ce membre est un pointeur à un objet, qui contient un membre nommé border, qui peut donc être désigné par :

document.body.style.border
""

La valeur de ce membre est une valeur caractère (""); comme il ne s’agit pas d’un pointeur à un objet, la chaîne ne pourrait pas être continuée.

Chacune des expressions :

est un chemin d’accès.

Un chemin d’accès sert souvent de nom pour identifier un membre qu’il faudrait autrement désigner par une périphrase, parfois très longue (la valeur border dans l’objet style dans l’objet body dans l’objet document) ! Cela nous permet, par exemple, de parler de « la chaîne de caractères document.body.style.border » ou de « l’objet document.body ».

Par souci d’uniformité, le nom d’un membre qui est directement dans l’environnement est aussi appelé « chemin d’accès ». L’expression :

document

est donc elle aussi un chemin d’accès. La même chose s’applique aux noms de variables, que l’on considère aussi être des « chemins d’accès ».

Chemins d’accès comme LHS

De la même façon qu’on peut créer ou modifier un membre dans l’environnement avec l’opérateur d’assignation "=", on peut utiliser le même opérateur pour créer ou modifier un membre d’un objet. Il suffit d’utiliser comme partie de gauche d’une assignation (la LHS) un chemin d’accès au membre en question, plutôt qu’un simple nom de variable.

Les exemples suivants ont été vus en classe :

document.title = "Bonjour le monde !"
"Bonjour le monde !"

document.bgColor = "blue"
"blue"

Un chemin d’accès peut bien sûr faire l’objet d’une auto-réassignation :

document.bgColor = "light" + document.bgColor
"lightblue"

Ces exemples sont des cas, évoqués plus tôt, de LHS qui ne sont pas de simples noms de variable. Nous en verrons d’autres en classe.

Fonctions

Revenons à l’objet Math. Cet objet est un de ces membres statutaires, évoqués plus tôt, qui fournissent des fonctionnalités essentielles pour la programmation en JS. En fait, Math est statutaire non seulement dans l’environnement navigateur Web, mais dans tous les types d’environnements JS. C’est un membre statutaire au langage JS lui-même ou intrinsèque au JS.

Si vous avez lu la digression ci-dessus, vous aurez vu que l’objet Math possède un membre abs, qui est un pointeur à un objet :

Math.abs
▸function abs()

Le mot function à droite de la puce "▸" nous indique qu’il s’agit d’un objet de type function.

Les objets de type function, sont appelés – de façon assez peu imaginative – « fonctions ». Métaphoriquement, ces objets possèdent, en plus d’un ensemble de tiroirs, une mécanique interne qui leur permet d’effectuer certains traitements sur des données qu’on leur fournit. C’est une généralisation du concept de fonction mathématique, comme +, -, ×, ÷, dont on peut imaginer qu’une « mécanique interne » leur permet d’effectuer un calcul sur les nombres qu’on leur fournit.

Dans le cas de Math.abs, le traitement effectué est le calcul de la fonction « valeur absolue », soit la valeur positive d’un nombre.

Invocation (ou appel) de fonction

Mais l’expression Math.abs en elle-même ne fait aucun calcul; comme nous venons de voir, elle ne fait que retourner un pointeur à l’objet qu’est la fonction Math.abs :

Math.abs
▸function abs()

Pour utiliser la fonction, autrement dit pour « déclencher sa mécanique interne », il faut l’invoquer (on dit aussi l’appeler ou l’exécuter), grâce à un type d’expression JS dont nous avons déjà vu quelques exemples (avec prompt(), alert(), Math.min(), etc.), sans toutefois lui donner un nom particulier : l’invocation de fonction, qui consiste à mettre entre parenthèses () après le nom de la fonction les données sur lesquelles on veut la faire travailler.

Ce qu’il faut écrire entre les parenthèses est dicté par le type et le nombre de valeurs sur lesquelles la fonction opère. Dans le cas de la valeur absolue, il s’agit d’une fonction qui s’applique à une seule valeur numérique, on utilisera donc une invocation de la forme :

Math.abs(-876)
876

où ce qu’on met entre parenthèses pourrait être n’importe quelle sous-expression donnant une valeur numérique.

Une valeur passée à une fonction lors d’une invocation de fonction est appelée argument de la fonction. On utilise aussi les mots « paramètre » ou « opérande ».

Certains membres statutaires de l’environnement navigateur Web sont des fonctions. Les fonctions prompt et alert vues précédemment en sont des exemples. L’une et l’autre doivent être invoquées avec une valeur caractère comme seul argument.

Nous avons déjà rencontré précédemment, dans un autre contexte, deux autres fonctions de l’objet Math : Math.min et Math.max qui doivent être invoquées avec deux arguments ou plus, que l’on sépare l’un de l’autre par une virgule :

Math.min(15, 10)
10

Une autre fonction est Math.random, qui génère un nombre aléatoire entre 0 et 1, qui n’exige aucun argument. Il faut quand même inscrire les parenthèses ( ), pour indiquer que la fonction doit bel et bien être invoquée :

Math.random()
0.8307841400124085

Comme le résultat est aléatoire, une deuxième invocation donne presque assurément un résultat différent :

Math.random()
0.920563795460914

Si on omet les parenthèses ( ), on obtient simplement la valeur de Math.random, qui est bien sûr un pointeur à une fonction :

Math.random
▸function random()

Si on essaie d’« invoquer » autre chose qu’un pointeur à une fonction, on obtient une erreur :

Math.PI(45)
Uncaught TypeError: Math.PI is not a function

Résultat retourné par une fonction

Le résultat retourné par une invocation de fonction, comme expression, est le résultat du « calcul », au sens large, effectué par la fonction sur les arguments soumis. Il s’agit toujours d’une seule valeur JS. Ce peut être une valeur numérique, caractère, un pointeur à un objet ou même une valeur autonyme (par exemple undefined).

Invocation de fonction comme sous-expression

Puisqu’une invocation de fonction est une expression JS, par la règle d’enchaînement, on peut l’intégrer comme sous-expression dans une expression plus longue. Sa valeur, comme sous-expression, est la valeur retournée par la fonction comme résultat de son invocation. Par exemple :

Math.random() + 100
100.03573473194079

Math.min(Math.max(100, 78), Math.max(-25, -30))
-25

Invocation de fonction dans un chemin d’accès

Le fait qu’une fonction puisse retourner un pointeur à un objet comme résultat amène la possibilité que certaines parties d’un chemin d’accès soient une invocation de fonction plutôt qu’un simple nom de membre.

Prenons un exemple : L’objet document, mentionné précédemment, est statutaire en environnement navigateur Web. Il possède un membre qui est la fonction document.querySelector. Cette fonction accepte comme argument une valeur caractère donnant le nom d’un élément HTML, mettons "p". Comme résultat, la fonction retourne un pointeur à un objet JS qui correspond au premier élément HTML <p> rencontré dans le document courant :

document.querySelector("p")
▸<p class="copy">

Vous pourriez obtenir un résultat différent. Puisque l’expression ci-dessus retourne (c’est-à-dire a comme valeur) un pointeur à un objet, on peut coller à sa droit un chemin d’accès permettant de naviguer à partir de cet objet :

document.querySelector("p").innerText.charAt(0)
"C"

Encore ici, vous pourriez obtenir un résultat différent.

La meilleure façon de comprendre ce chemin d’accès est de réaliser qu’il est parfaitement équivalent à la suite suivante d’énoncés, où vtrav est une variable de travail, introduite exclusivement pour « couper en deux » le chemin d’accès :

vtrav = document.querySelector("p")
▸<p class="copy">

vtrav.innerText.charAt(0)
"C"

Convention de notation pour les fonctions

Tel que mentionné précédemment, il est d’usage, dans le monde de l’orienté-objet, quand on nomme (le plus souvent, par un chemin d’accès) un objet qui est une fonction, d’inscrire des parenthèses vides juste après son nom, pour mettre en évidence le fait qu’il s’agit d’une fonction. On parlera ainsi de Math.abs(), au lieu de dire « la fonction Math.abs ». Nous suivons cette convention partout dans le cours, à l’exception de la présente sous-section, où la distinction entre le nom d’une fonction et son invocation était de première importance.

Notons que le fait d’utiliser les parenthèses vides indique simplement qu’il s’agit d’une fonction et ne présume pas que la fonction doive être invoquée sans argument – même si cela peut être le cas, comme pour Math.random().

Règles sur les noms de membre

Jusqu’à maintenant, les seuls membres nommés par la programmeuse sont les variables. Nous verrons plus tard dans le cours d’autres situations où la programmeuse doit choisir un nom de membre, par exemple lorsqu’elle crée ses propres fonctions. Les mêmes règles que pour les noms de variable s’appliquent alors. Notons que certains membres statutaires ou qui ne sont pas créés par assignation peuvent porter un nom qui ne respecte pas ces règles.

Propriétés et méthodes

Certains auteurs classent les différents membres d’un objet ou de l’environnement en deux groupes : les propriétés et les méthodes. Un membre est considéré « méthode » s’il pointe à une fonction et « propriété » dans tous les autres cas. Ce sont des appellations courantes dans la terminologie de l’orientation-objet. Cependant, en JS, la distinction est peu utile, étant donné que la valeur d’un membre peut passer d’un type à un autre par simple assignation. Une méthode peut donc devenir une propriété, et vice-versa, à la suite d’une simple assignation.

Même s’il nous arrivera régulièrement d’utiliser le mot propriété, dans le sens ci-dessus, nous préférons habituellement le terme plus général de « membre ». Bien entendu, un membre non statutaire de l’environnement est le plus souvent appelé simplement « variable ».


Autres utilisations de l’opérateur « . »

Comme nous avons évoqué précédemment, l’opérateur « . » peut aussi être utilisé avec, à gauche, une valeur simple, pas seulement un pointeur à un objet. On peut imaginer que, lors de l’application de l’opérateur « . » à une valeur simple, JS crée un objet temporaire avec certains membres prédéfinis en fonction du type de la valeur simple, puis utilise un pointeur à cet objet temporaire comme argument de gauche de l’opérateur « . ». Après exécution de l’expression, l’objet temporaire est simplement détruit, c’est-à-dire éliminé de la mémoire de l’interprète JS.

Nous avons déjà vu plus haut certaines opérations (.length, .charAt(), etc.) s’exprimant avec l’opérateur « . » précédé d’une valeur caractère. Lorsque l’opérateur point est utilisé avec à gauche une valeur caractère, l’objet temporaire créé par l’interprète JS comporte comme membres prédéfinis :

C’est ce qui justifie la syntaxe particulière de ces opérations : le point est réellement l’opérateur « . », mais appliqué à un objet temporaire, qui n’est jamais directement visible.

Un autre cas intéressant est celui où l’opérateur point est précédé d’une valeur numérique. L’objet temporaire créé par JS contient alors comme membre la fonction toFixed(). On peut donc considérer .toFixed() comme une opération applicable à toute valeur numérique :

.toFixed()

Appliquée à une valeur numérique, .toFixed() arrondit la valeur au nombre de décimales donné en argument (zéro si l’argument est omis), puis la transforme en chaîne de caractères :

(112*1.15).toFixed(2)
"128.80"

(1.15).toFixed(5)
"1.15000"

Math.PI.toFixed(3)
"3.142"

Math.PI.toFixed(0)
"3"

Math.PI.toFixed()
"3"


Annexe

Exemple d’enchaînement d’expressions

L’exemple suivant illustre la règle d’enchaînement d’expressions.

Nous savons que 345 + 3 et 10 - 12 sont toutes deux des expressions bien formées. La règle d’enchaînement d’expressions nous dit que les quatre constructions suivantes sont aussi des expressions bien formées :

10 - 12 + 3    (nous avons remplacé 345 par 10 - 12)
345 + 10 - 12    (nous avons remplacé 3 par 10 - 12)
10 - 345 + 3    (nous avons remplacé 12 par 345 + 3)
345 + 3 - 12    (nous avons remplacé 10 par 345 + 3)

En d’autres mots, la règle d’enchaînement nous dit qu’il est possible de mettre plusieurs opérations dans la même expression.

Il n’y a aucune limite sur le nombre d’expressions que l’on peut ainsi « enchaîner » par la règle d’enchaînement.