Objectifs: Le but de ce TD est de vous faire expérimenter les constructions de base du langage JavaScript (types simples, déclarations de variables, instructions de contrôle, itérations) qui sont très proches syntaxiquement de celles utilisées par le langage C. Les programmes que vous aurez à écrire ne font appel qu'aux constructions de base du langage JavaScript (Core JavaScript) mis à part pour la lecture de valeurs au clavier. C'est pourquoi afin de simplifier leur écriture et leur exécution, vous utiliserez l'environnement Node.js qui vous affranchira de l'intégration de vos scripts dans du code HTML et de l'utilisation d'un navigateur.
Les
exercices proposés dans ce TP sont indépendants et sont organisés selon 4
thèmes
thèmes : expressions , instructions conditionnelles, itérations, fonctions. Une 5ème partie
propose
un ensemble d'exercices que vous pourrez réaliser de manière facultative
pour vous entrainer.
Ressources utiles
-
Les supports de cours pour l'introduction à JavaScript:
-
La documentation JavaScript in Visual Studio Code pour le support de JavaScript dans VSCode.
Prenez dès maintenant de bonnes habitudes de codage JavaScript. Il vous est demandé de respecter impérativement les 3 règles ci-dessus.
- tout programme source JavaScript doit avoir comme suffixe .js.
- Les noms de variables et de fonctions sont définis par un identificateur débutant par une minuscule (camelCase).
- Les programmes doivent être correctement indentés. (Utilisez l'outil d'identation automatique de VSCode !)
1. Prise en main de l'environnement de développement
Avant toute chose, vérifiez que Node.js est bien installé sur votre machine. Pour cela ouvrez un terminal et tappez la commande node --version, le numéro de la version de Node.js installée sur votre machine est alors affiché, par exemple v18.14.2.
Si la commande node n'est pas reconnue, vous devez télécharger et installer Node.js avant de continuer.
1.1 Créer et exécuter un programme JavaScript dans VSCode
Pour la réalisation de ce TP vous avez besoin d'un éditeur de texte et d'un environnement
Javascript (Node.js). Pour
exécuter un programme JavaScript contenu dans un fichier monProgramme.js
il suffit
d'ouvrir un terminal
dans le répertoire contenant ce fichier et d'éxécuter la commande
node monProgramme.js
Cependant il est possible de tout faire depuis l'IDE VScode comme vous allez pouvoir l'expérimenter dans l'exercice qui suit
1) Creez un fichier JavaScript HelloWorld.js

2) Editer le fichier HelloWorld.js
Dans HelloWorld.js tappez le code suivant
console.log("Hello World !");
VScode utilise IntelliSense pour l'édition du code et offre de nombreuses possibilités d'autocomplétion du code comme indiqué sur la figure ci dessous.

3) Exécuter le programme HelloWorld.js
Une fois votre code écrit et enregistré vous pouvez directement l'exécuter en ouvrant un terminal dans VSCode et en invoquant l'interpréteur de Node.js

1.2 Utiliser les modules (packages) Node
1.2.1 Lire des données au clavier avec readline-sync
console.log
est une fonction standard de JavaScript qui permet d'afficher du texte
sur la console de votre environnement
d'exécution JavaScript (que ce soit un navigateur ou Node.js). Par contre, Core Javascript tel
qu'il est défini par le standard
ECMAScript ne définit pas de moyen de saisir des données à partir du clavier. La manière de
procéder va dépendre de votre environnement
d'éxécution. En ce qui concerne Node.js, nous allons utiliser un module complémentaire
(readline-sync)
qu'il va falloir installer à l'aide de
npm, le gestionnaire de paquets (ou modules) officiel de Node.js (voir
Node.js NPM).

-
Installez le module readline-sync pour pouvoir l'utiliser dans vos programmes
- Constatez que Node.js a créé dans votre répertoire TP05 deux fichier de configuration package.json et package.lock.json et un répertoire node_modules qui contient le code du modules realine-async et des autres modules dont ce dernier dépend.
-
Importez le module à l'aide d'une instruction require que vous placerez au debut de votre programme
const readline = require('readline-sync');
-
ensuite pour invoquer l'une des fonctions du module il suffit de préfixer l'appel par readline.. Par exemple :
let prenom = readline.question("entrez votre prénom ");
permet d'invoquer la fonction question qui affiche un message sur la console et attend un réponse de l'utilisateur. Une fois que l'utilisateur a saisi sa réponse la valeur de celle-ci est renvoyée et ici est stockée dans la variable prenom.
readline-sync propose différentes fonctions (méthodes) selon la nature de la valeur que vous voulez saisir.
- question() qui renvoie une chaîne de caractères (valeur de type string)
- questionInt() qui renvoie une valeur entière (valeur de type number)
- questionFloat() qui renvoie une valeur réelle (valeur de type number)
Se référer à la documentation de readline-sync pour voir le detail des ces fonctions et leurs différents paramètres d'appel.
1.2.2 Modules CommonJS vs. Modules ES6 (ECMA Script 6)
Lorsque en 2009 Node.js a été créé, il n'existait pas de système de modules standardisé pour JavaScript. Pour combler ce vide et fournir un moyen de modulariser le code, l'équipe de Node.js a développé son propre système : CommonJS. C'est CommonJS que nous avons utilisé dans l'exercice précédent pour importer readline-sync avec l'instruction require.
En 2015 la spécification ES6 (ECMA Script 6) qui définit la norme JavaScript a, elle aussi, intégré la notion de modules mais avec une syntaxe différente de celle de CommonJS. Ces modules ES6 (également connus sous le nom de modules ECMAScript ou ESM) présentent des avantages tels que l'analyse statique, un meilleur support pour le chargement asynchrone et une syntaxe standardisée à travers les environnements JavaScript (côté client et serveur)
Node.js prend désormais en charge les deux systèmes de modules (CommonJS et ESM). Cependant pour assurer la compatibilité rétroactive avec le grand nombre de projets et de modules Node.js déjà existants et développés en utilisant CommonJS, Node.js a conservé CommonJS comme système de modules par défaut.
Modifiez votre programme HelloWorld.js pour utiliser la syntaxe ESM (ES Modules)
-
Dans HelloWorld.js remplacez
const readline = require('readline-sync'); // importation du module readline-sync avec CommonJS
par
import readline from 'readline-sync'; // importation du module readline-sync avec ESM
-
Essayez d'exécuter à nouveau votre programme et constatez qu'une erreur se produit
C'est normal ! Comme dit précédemment, Node.js supporte par défaut la syntaxe CommonJS, pour travailler avec la syntaxe ESM (modules ES6) deux possibilité vous sont proposées
-
soit utiliser l'extension de fichier .mjs pour les fichiers sources utilisant la syntaxe ESM
-
soit définir dans votre fichier package.json.
Nous allons adopter la deuxième solution.
-
-
Modifiez le fichier package.json pour y ajouter "type": "module" après la déclaration des dépendances
-
Après avoir sauvegardé package.json réexécutez votre programme HelloWrorld.js et constatez que maintenant l'instruction import est reconnue et que le programme fonctionne correctement.
Remarque : si maintenant vous vouliez écrire du code JavaScript en utilisant la syntaxe Common.js, il faudrait utiliser l'extension .cjs au lieu de .js pour votre fichier source.
2. Expressions
Exercice 1 : Conversion de températures
En utilisant la formule \(tempC = (5/9)(tempF-32)\) écrire en langage JavaScript un programme
degres.js
qui lit une température exprimée en degrés
Fahrenheit et affiche sa valeur en degrés centigrades ou degrés
Celsius.
Exemples d'exécution du programme (en vert les valeurs introduites par l'utilisateur) :
P:\TW\TP05>node degres.js
donnez une temperature en Fahrenheit : O.O
cette temperature equivaut a -17.8 degres Celsius
P:\TW\TP05>node degres.js
donnez une temperature en Fahrenheit : 60.0
cette temperature equivaut a 15.6 degre Celsius
P:\TW\TP05>
Par défaut, lorsqu'un nombre flottant est affiché sur la console, tous les chiffres qu'il contient après le séparateur décimal apparaissent. Ainsi le code
let x = 17/7;
console.log("x = " + x);
donne l'affichage suivant
x = 2.4285714285714284
Il est néanmoins possible de formatter les nombres pour fixer le nombre de chiffres à
conserver après
le point décimal à l'aide de la méthode toFixed
(voir w3schools
ou MDN)
Exercice 2 : Conversion de durées
Ecrire un programme hjms.js
en langage JavaScript qui pour un nombre de
secondes donné calcule et affiche son équivalent en nombre de
jours, d'heures, de minutes et de secondes.
exemples d'exécution du programme :
P:\TW\TP05>node hjms donnez une durée en secondes : 235789 cette durée equivaut à 2 jours 17 heures 29 minutes 49 secondes P:\TW\TP05>node hjms donnez une durée en secondes : 567231 cette durée équivaut à 6 jours 13 heures 33 minutes et 51 secondes P:\TW\TP05>
L'opérateur %
(modulo) permet d'obtenir le reste de la division
entière de deux nombres. Par exemple
console.log("17 % 7 --> " + 17 % 7);
console.log("17 / 7 --> " + 17/7);
donne l'affichage suivant
17 % 7 --> 3
17 / 7 --> 2.4285714285714284
Pour obtenir la division entière de 17 par 7 (qui vaut 2) il faut passer par la méthode
Math.floor
(voir
w3schools
ou MDN)
3. Instructions conditionnelles
Exercice 1 : Améliorer le programme de conversion de durées
Si ce n'est déjà fait, améliorez votre programme hjms.js
de sorte que
lorsqu'une valeur (nombre de jours, d'heures , de minutes ou de secondes) est nulle
elle n'apparaisse pas dans l'affichage, et que si elle vaut 1 l'unité soit affichée au
singulier (sans s) comme dans l'exemple ci-dessous.
P:\TW\TP05>node hjms donnez une durée en secondes : 3621 Cette durée equivaut à 1 heure 21 secondes P:\TW\TP05>
Exercice 2 : Classer 3 nombres
Ecrire un programme troisNombres.js
qui lit 3 nombres au clavier et les affiche sur la console dans l'ordre croissant
(du plus petit au plus grand).
P:\TW\TP05>node troisNombres 1er nombre : 14 2ème nombre : 10 3ème nombre : 17 les nombres dans l'ordre croissant : 10 14 17 P:\TW\TP05>
4. Itérations
Exercice 1 : Affichage de motifs - escaliers
Ecrire un programme qui affiche un motif triangulaire dont la taille est fixée par une valeur lue au clavier.
Exemple de trace d'exécution:
P:\TW\TP05>node triangle1 donnez taille du motif : 7 * ** *** **** ***** ****** ******* P:\TW\TP05>
a) écrire un programme triangle1.js
affichant
ce motif en utilisant uniquement des instructions tant que
(while()).
b) écrire un programme triangle2.js
affichant
ce motif en utilisant uniquement des instructions pour
(for).
Exercice 2 : Affichage de motifs - pyramides
Même exercice que le précédent mais le motif affiché n'est plus un triangle mais une pyramide (voir ci-dessous) et le choix des instructions pour le réaliser est laissé à votre jugement.
Exemple de trace d'exécution (en vert les valeurs introduites par l'utilisateur):
P:\TW\TP05>node pyramide donnez taille du motif : 7 * *** ***** ******* ********* *********** ************* P:\TW\TP05>
5. Fonctions
Exercice 1 : Moyenne olympique
Ecrivez un programme
moyenneOlympique.js
qui lit au clavier une séquence de nombres réels positifs
ou nuls (correspondant à des notes comprises entre 0 et 10), séquence terminée par la valeur -1,
et calcule la moyenne olympique de ces valeurs, c'est à dire la moyenne
des notes sans prendre en compte la note la plus élevée ni la
note la moins élevée (c'est ce qui se passe dans les compétitions de gymnastique ou de
patinage artistique
pour limiter les abus dans la notation).
Exemple de trace d'exécution (en vert les valeurs introduites par l'utilisateur):
P:\TW\TP05>node moyenneOlympique.js Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 7.89 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 8.76 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 8.45 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 9.10 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 14.75 Valeur incorrecte. Recommencez ! Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 7.75 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 9.30 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : 7.50 Donner un note entre 0 et 10 (-1 pour terminer la saisie) : -1 Nombre de notes saisies 7 La note la plus élevée (9.3)et la note plus basse (7.5) ont été retirées La moyenne olympique est : 8.39 P:\TW\TP05>
Pour l'écriture de ce programme, vous devez utiliser uniquement des variables de type primitif et ne pas vous servir d'un tableau ou d'une liste
Pour la lecture des notes, vous écrirez une fonction lireNote
qui effectue la saisie d'une note et vérifie que celle-ci est correcte. Les traitements effectués par cette
fonctions sont les suivants:
- afficher le message d'invite (prompt) indiquant l'intervalle de validité des notes et la valeur de fin de séquence.
- lecture d'une valeur
- vérification que cette valeur est bien dans l'intervalle de valeurs autorisées ou est égale à la valeur de fin de séquence. Si c'est le cas la valeur lue est retournée, sinon un message d'erreur est affiché est une nouvelle valeur est demandée à l'utilisateur.
Exercice 2: Créer et utiliser un module ESM
Dans les programmes degres.js
et hjms.js
, vus lors de l'exercice
1,
il n'est possible de faire qu'une seule saisie. Si l'utilisateur veut effectuer
plusieurs conversions, il doit relancer l'exécution du programme. On souhaite modifier
le comportement de ces programmes de manière à ce que l'utilisateur puisse
renouveler le traitement jusqu'à ce qu'il dise explicitement qu'il désire terminer
l'exécution.
Le déroulement de l'exécution de ces programmes serait alors le suivant :
P:\TW\TP05>node degres2.js
donnez une température en degrés Fahrenheit : 32
la température en degrés Celsius est 0.00
voulez-vous recommencer ? (O/N): O
donnez une température en degrés Fahrenheit : 45
la température en degrés Celsius est 7.22
voulez-vous recommencer ? (O/N): 33
désolé nous n'avons pas compris votre réponse
voulez-vous recommencer ? (O/N): o
donnez une température en degrés Fahrenheit : 23
la température en degrés Celsius est -5.00
voulez-vous recommencer ? (O/N): n
Au revoir !
P:\TW\TP05>node hjms
entrez une durée (en sec.) : 345678
Cette durée equivaut à 4 jours 1 minute 18 secondes
encore ? (O/N): o
entrez une durée (en sec.) : 3567912
Cette durée equivaut à 41 jours 7 heures 5 minutes 12 secondes
encore ? (O/N): p
désolé nous n'avons pas compris votre réponse
encore ? (O/N): n
P:\TW\TP05>
a) Pour cela vous allez écrire une fonction encore
qui affiche
un message
demandant à l'utilisateur si il veut poursuivre ou non le traitement et qui selon la valeur
saisie
retourne un booléen (true si il veut poursuivre, false
sinon).
.
Dans un premier temps écrivez et testez cette fonction dans le programme
degres.js
.
b) Ensuite pour pouvoir utiliser cette fonction dans d'autres programmes
(par exemple hjms.js
)
il vaut mieux l'isoler dans un module que vous pourrez importer à la manière du module
readline-async
utilisé pour les lectures au clavier. Pour cela procédez comme
suit :
-
créez un fichier
utils.js
-
couper le code la function
encore
dans le fichierdegres.js
et collez le dansutils.js
-
modifiez la signature de la fonction en précédant sa déclaration d'une directive
export
comme indiqué ci dessous// pour utiliser le module readline import readline from 'readline-sync'; export function encore(message) { .... les instructions de la fonction }
-
pour utiliser la fonction dans un autre de vos programmes, utilisez une instruction
import
comme pourreadline-async
pour importer le moduleimport readline from "readline-sync"; // pour utiliser le module readline-sync import { encore } from "./utils.js"; // pour utiliser la fonction encore du module utils
Modifiez les programmes degres.js
et hjms.js
pour permettre à
l'utilisateur d'effectuer autant de traitements
qu'il le souhaite.
6. Exercices supplémentaires
Les exercices de cette partie sont facultatifs, faites les pour vous entrainer lorsque vous aurez du temps
Exercice 1 : Tester si un nombre est premier
Un nombre est n premier si il a seulement deux diviseurs : 1 et n.
Ecrire un programme Premier.js
qui permet de tester si un
nombre introduit par l'utilisateur est premier ou non.
Exemple de trace d'exécution (en vert les valeurs introduites par l'utilisateur):
P:\TW\TP05>node Premier donnez un entier positif : 7 7 est un nombre premier Voulez-vous essayer un autre nombre O/N ? o donnez un entier positif : 25 25 n'est pas un nombre premier, il est divisible par 5 Voulez-vous essayer un autre nombre O/N ? n Au revoir P:\TW\TP05>
Exercice 2 : Suite de Fibonacci
La suite de Fibonacci est définie par la formule de récurrence suivante:
u0 = 0 u1 = 1 un = un-1 + un-2 (pour n >= 3)
a) Ecrire un programme Fibo1.js
qui permet de calculer le nième terme de la suite de Fibonacci,
n étant fixé par l'utilisateur.
b) Ecrire un programme Fibo2.js
qui permet d'obtenir la valeur et le rang du premier terme de cette suite supérieure
à une valeur donnée par l'utilisateur.
Exercice 3 : Prix d'un lot
Le jeu consiste à découvrir par essais successifs le prix d'un lot . Pour chaque essai, le joueur reçoit un message : "Trop grand", "Trop petit" ou "BRAVO ! Vous avez trouvé en K essais". Le jeu est fini quand le joueur a trouvé le prix du lot.
Exercice 3.1 : Ecrivez un programme JavaScript PrixLot1.js
qui joue
le rôle de meneur de jeu ; l'exécution de ce programme vous fera
tenir le rôle du joueur. Le programme Prixlot1
doit définir
le prix du lot en tirant un entier aléatoire entre 1 et 1000 et dialoguer
avec le joueur pendant le jeu.
Pour choisir un nombre au hasard on utilisera la méthode random
de la classe Math
qui retourne un réel (double) tiré
au hasard et de manière uniforme dans l'intervalle [0 1].
exemple :
double x;
x = Math.random();
exemple d'exécution du programme PrixLot1
P:\TW\TP05>node PrixLot1 Le but est de chercher un prix entre 0 et 1000 Tapez un prix : 566 Trop grand Tapez un prix : 400 Trop grand Tapez un prix : 150 Trop petit Tapez un prix : 200 Trop petit Tapez un prix : 214 BRAVO ! Vous avez gagné en 5 essais P:\TW\TP05>
Exercice 3.2 : Copier dans le fichier PrixLot2.js
le fichier
PrixLot1.js
, et modifier PrixLot2.js
de manière
à pouvoir :
-
enchaîner plusieurs jeux consécutifs lors d'une même exécution du programme (à la fin de chaque jeu, il est demandé au joueur de préciser s'il veut s'arrêter ou rejouer)
-
limiter le nombre d'essais du joueur lors d'une partie (au début de chaque partie, le programme demandera le nombre maximum d'essais autorisés).
Exemple d'exécution du programme PrixLot2
P:\TW\TP05>node PrixLot2 Le but est de chercher un prix entre 0 et 1000 1ère partie. Nombre maximum d'essais : 4 Tapez un prix : 678 Trop petit Tapez un prix : 920 Trop grand Tapez un prix : 860 Trop petit Tapez un prix : 910 Trop petit PERDU ! Vous avez épuisé le nombre d'essais autorisés Le prix était : 917 Voulez-vous rejouer O/N ? o 2ème partie. Nombre maximm d'essais : 8 Tapez un prix : 678 Trop grand Tapez un prix : 333 Trop grand Tapez un prix : 300 Trop petit Tapez un prix : 320 Trop petit Tapez un prix : 324 BRAVO ! Vous avez gagné en 5 essais Voulez-vous rejouer O/N ? n P:\TW\TP05>
Exercice 3.3 : En jouant avec le programme précédent, essayer
de trouver une stratégie systématique et efficace. Ecrire un programme
PrixLot3.js
qui fait jouer l'ordinateur à votre place suivant
la tactique que vous venez de définir ; les deux rôles de meneur
de jeu et de joueur sont donc à la charge du programme, le joueur "ignorant"
évidemment le prix connu du meneur de jeu, mais "sachant" si son essai
est plus grand ou plus petit que le prix.
Le programme PrixLot3
effectue 20 parties ; il affiche pour chaque
partie le prix tiré au sort et le nombre d'essais successifs qui ont
été nécessaires pour le trouver avec la tactique programmée.
Pouvez-vous prévoir, pour la tactique que vous avez choisie, l'ordre
de grandeur des nombres d'essais ? Compléter le programme PrixLot3
en lui faisant calculer la moyenne des 20 nombres d'essais obtenus pour les
20 parties.
Exercice 4 : Valeur approchée de la racine carrée d'un nombre réel positif
On considère un nombre réel positif A ; on sait que la suite (un) n=0,1,2,... définie par la donnée d'un réel u0 positif et par la relation de récurrence un = (un-1 + A / un-1) * 0,5 (pour n > 0) converge vers la racine carrée de A . On suppose le nombre A compris entre 1 et 100, et on prend u0 = A / 2.
Pour obtenir une valeur approchée de racine carrée de A, on cherche le premier terme un tel que | un2 - A | < E-5 . Le nombre trouvé est une valeur approchée de racine carrée de A ( en effet | un2 - A | < E-5 implique que | un- rac(A) | < E-5 / ( un+ rac(A) où rac(A) correspond à la racine carrée de A).
a) Ecrivez un programme JavaScript Raca1.js
qui permet
-
de lire le nombre A,
-
de calculer et d'afficher les approximations intermédiaires et la valeur approchée de la racine carrée de A définie ci-dessus.
Exemple de l'état de l'écran obtenu par exécution du programme Raca1
:
Entrer un nombre A entre 1 et 100: 19.23 Approximations successives : u0 = 9.615 u1 = 5.8075 u2 = 4.559367735686612 u3 = 4.388528900180239 u4 = 4.385203650605606 Valeur approchée de la racine carrée = 4.385202389856321
Indications pour écrire le programme :
- définir une constante :
const EPS = 1E-5;
- utiliser une boucle tant que :
while (. . . . . . . >= EPS) {
. . . . . . . . .
}
b) à partir du programme Raca1.js
écrire un
programme Raca2.js
qui vérifie que le nombre introduit au
clavier est bien un nombre positif supérieur à 1, et dans le cas
contraire affiche un message d'erreur et redemande une nouvelle valeur à
l'utilisateur.