Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 217 minDébutant

Variables, types et opérateurs : let, const et ===

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • déclarer une variable avec const ou let, et dire pourquoi éviter var ;
  • reconnaître les types de données et les vérifier avec typeof ;
  • convertir une saisie en nombre sans piège ;
  • comparer avec === et prévoir le résultat d'une condition.

4 exercices corrigés

Une variable JavaScript est un nom qui désigne une valeur ; on la déclare avec const quand elle ne sera pas réaffectée, avec let sinon. Ce chapitre présente les déclarations, les types de données du langage, les conversions entre types, et les opérateurs, avec les pièges qui surprennent tous ceux qui viennent d'un autre langage. Les notions générales (variable, affectation, type) sont expliquées dans le cours Algorithmique : ici, on regarde comment JavaScript les applique.

Déclarer une variable : const, let, et pourquoi oublier var

js
const TAUX_TVA = 0.2;          // ne changera pas : const
let quantite = 12;             // va changer : let
quantite = quantite - 1;       // réaffectation autorisée avec let
console.log(quantite);         // 11

La règle du code moderne : const par défaut, let quand la variable doit être réaffectée, jamais var. Une variable déclarée avec const ne peut pas recevoir une autre valeur : si tu essaies, le navigateur s'arrête sur TypeError: Assignment to constant variable. C'est une protection, pas une contrainte : en lisant const, tu sais que la valeur ne bougera plus.

var est l'ancienne façon de déclarer, d'avant 2015. Elle a deux défauts qui causent des bugs difficiles à trouver :

js
console.log(stock);   // undefined : pas d'erreur, alors que stock n'est pas encore déclaré
var stock = 5;

if (true) {
  var message = 'visible partout';
}
console.log(message); // 'visible partout' : var ignore les blocs { }

Avec let ou const, lire une variable avant sa ligne de déclaration provoque une erreur claire (ReferenceError: Cannot access 'stock' before initialization), et une variable déclarée dans un bloc { } n'existe que dans ce bloc. Tu croiseras var dans du code ancien ; ne l'écris pas.

varletconst
PortéeLa fonction entièreLe bloc { }Le bloc { }
RéaffectationOuiOuiNon
Redéclaration du même nomOui, sans erreurNon (SyntaxError)Non (SyntaxError)
Lecture avant la déclarationundefinedReferenceErrorReferenceError
À utiliserJamaisCompteurs, totaux, valeurs qui évoluentTout le reste

Nommer les variables

Un nom commence par une lettre, _ ou $, puis contient des lettres, des chiffres, _ ou $. JavaScript distingue majuscules et minuscules : quantite et Quantite sont deux variables différentes. Les conventions du langage :

  • camelCase pour les variables et les fonctions : prixUnitaire, seuilAlerte, valeurStock ;
  • PascalCase pour les classes : Piece ;
  • MAJUSCULES_SÉPARÉES pour les constantes de configuration connues à l'avance : TAUX_TVA, URL_API.

Choisis des noms qui disent ce que contient la variable : quantite plutôt que q, piecesEnAlerte plutôt que tab2. Les accents sont autorisés dans les noms mais déconseillés : les claviers de tes collègues et certains outils les gèrent mal. Les mots réservés du langage (let, class, function, return, new, delete…) ne peuvent pas servir de nom.

Les types de données en JavaScript

JavaScript est typé dynamiquement : tu ne déclares pas le type d'une variable, c'est la valeur qui a un type, et une même variable peut recevoir une valeur d'un autre type. Le langage connaît huit types : sept types primitifs et les objets.

TypeExemplestypeof renvoieÀ savoir
number12, 42.9, -3, NaN, Infinity'number'Un seul type pour les entiers et les décimaux
string'SSD-512', "Écran", `${q} pièces`'string'Immuable : on ne modifie pas un caractère
booleantrue, false'boolean'
undefinedundefined'undefined'Variable déclarée sans valeur, propriété absente
nullnull'object'« Pas de valeur », écrit volontairement ; typeof se trompe, c'est une erreur historique du langage
bigint9007199254740993n'bigint'Entiers de taille illimitée, rares en web
symbolSymbol('id')'symbol'Identifiants uniques, usage avancé
object{ ref: 'SSD-512' }, [1, 2], new Date()'object' ('function' pour une fonction)Tout ce qui n'est pas primitif, tableaux et fonctions compris
js
typeof 42            // 'number'
typeof 'Écran'       // 'string'
typeof undefined     // 'undefined'
typeof null          // 'object'   (piège)
typeof []            // 'object'   (un tableau est un objet)
typeof (() => 1)     // 'function'
Array.isArray([])    // true       (la bonne façon de tester un tableau)

Pour tester null, écris valeur === null, jamais typeof valeur === 'null' (toujours faux).

Les nombres : décimaux, arrondis et NaN

Tous les nombres sont des nombres à virgule flottante sur 64 bits (norme IEEE 754), comme le double de C#. Conséquence : certains décimaux ne sont pas représentés exactement.

js
0.1 + 0.2              // 0.30000000000000004
1.1 + 2.2              // 3.3000000000000003
(2.345).toFixed(2)     // '2.35'  : une chaîne, pas un nombre
(1.005).toFixed(2)     // '1.00'  : 1.005 est stocké un peu en dessous de 1,005
Math.round(2.5)        // 3
Math.round(-2.5)       // -2
7 % 3                  // 1   (reste de la division entière)
2 ** 10                // 1024 (puissance)
10 / 0                 // Infinity : pas d'erreur
0 / 0                  // NaN

NaN (Not a Number) est le résultat d'un calcul impossible, par exemple Number('douze'). Il a deux propriétés déroutantes : il est de type number, et il n'est égal à rien, pas même à lui-même (NaN === NaN vaut false). Teste-le avec Number.isNaN(valeur). Un NaN se propage : NaN + 1 vaut NaN, et tout calcul qui en dépend aussi.

Les chaînes de caractères et les gabarits

Une chaîne s'écrit entre apostrophes '…', guillemets "…" ou accents graves `…`. Les accents graves créent un gabarit (template literal) : tu y insères une expression avec ${…}, et tu peux aller à la ligne.

js
const ref = 'RAM-16';
const quantite = 3;
console.log(`${ref} : ${quantite} pièce${quantite > 1 ? 's' : ''} en stock`);
// RAM-16 : 3 pièces en stock

Les méthodes de chaîne que tu utiliseras le plus :

ÉcritureRésultatRôle
'SSD NVMe 512 Go'.length15Nombre de caractères
' ssd-512 '.trim().toUpperCase()'SSD-512'Retirer les espaces autour, passer en majuscules
'SSD-512'.includes('512')trueContient ?
'ram-16'.startsWith('RAM')falseCommence par ? (sensible à la casse)
'SSD-512'.slice(0, 3)'SSD'Extraire (début inclus, fin exclue)
'SSD-512'.slice(-3)'512'Les 3 derniers caractères
'SSD-512'.split('-')['SSD', '512']Découper en tableau
String(7).padStart(3, '0')'007'Compléter à gauche
'Dalle 15,6 pouces'.replace(',', '.')'Dalle 15.6 pouces'Remplacer la première occurrence (replaceAll pour toutes)
'Réparinfo'.at(-1)'o'Caractère à une position, négative depuis la fin

Une chaîne est immuable : s[0] = 'X' ne fait rien. Les méthodes renvoient toujours une nouvelle chaîne, qu'il faut ranger dans une variable.

Les conversions de type

Une saisie de formulaire est toujours une chaîne, même dans un champ type="number". Avant de calculer, convertis-la explicitement.

js
Number('12')          // 12
Number(' 42 ')        // 42   (espaces ignorés)
Number('')            // 0    (attention : un champ vide devient 0)
Number('12abc')       // NaN
Number('3,5')         // NaN  (la virgule française n'est pas comprise)
parseInt('12abc', 10) // 12   (lit le début, s'arrête au premier caractère invalide)
parseFloat('3.5 kg')  // 3.5
String(12)            // '12'

Number est strict : la chaîne entière doit être un nombre. parseInt et parseFloat sont tolérants et lisent ce qu'ils peuvent : pratique pour '3.5 kg', dangereux pour une saisie qu'on veut contrôler. Passe toujours la base 10 à parseInt. Pour accepter une virgule décimale, remplace-la avant : Number(saisie.replace(',', '.')).

JavaScript convertit aussi tout seul quand tu mélanges les types, et c'est la source de bugs classiques :

ExpressionRésultatPourquoi
'5' + 3'53'+ avec une chaîne concatène
'5' - 32- n'existe que pour les nombres : la chaîne est convertie
'5' * '2'10idem pour *
true + 12true devient 1
null + 11null devient 0
undefined + 1NaNundefined devient NaN
'1' + 12 + 1'1121'De gauche à droite : '1' + 12 donne '112'
12 + 1 + '1''131'12 + 1 donne 13, puis concaténation

Comparer : == ou === ?

=== (égalité stricte) compare la valeur et le type, sans conversion. == (égalité large) convertit d'abord, avec des règles si tordues que presque personne ne les connaît par cœur :

js
0 == ''              // true
0 == '0'             // true
'' == '0'            // false  (pourtant les deux sont égaux à 0…)
null == undefined    // true
null === undefined   // false
3 === '3'            // false

Utilise toujours === et !==. Les outils d'analyse de code comme ESLint ont une règle pour l'imposer à toute une équipe (eqeqeq).

Les comparaisons <, >, <=, >= entre deux chaînes comparent l'ordre des caractères, pas les nombres : '10' < '9' vaut true, parce que le caractère '1' vient avant '9'. Encore une raison de convertir les saisies.

Valeurs « truthy » et « falsy »

Dans un if, n'importe quelle valeur est convertie en booléen. Seules huit valeurs deviennent false : on les appelle falsy.

Valeurs falsyTout le reste est truthy, y compris
false, 0, -0, 0n, '', null, undefined, NaN'0', 'false', ' ', [], {}, -1
js
const nom = '';
if (nom) {
  console.log('nom saisi');
} else {
  console.log('nom vide');   // affiché : '' est falsy
}

C'est pratique pour tester une chaîne vide, mais piégeux avec les nombres : une quantité de 0 est falsy, alors que c'est une vraie quantité.

Les opérateurs

FamilleOpérateursExemple
Arithmétiques+ - * / % **quantite * prix
Affectation= += -= *= /= ??=total += prix
Incrément++ --i++
Comparaison=== !== < > <= >=quantite <= seuil
Logiques&& || !quantite > 0 && !enAlerte
Coalescence des nuls??fournisseur ?? 'inconnu'
Ternairecondition ? a : bquantite > 1 ? 's' : ''

&& et || ne renvoient pas forcément un booléen : ils renvoient l'une des deux valeurs. a || b renvoie a s'il est truthy, sinon b. a ?? b renvoie a sauf s'il vaut null ou undefined. La différence compte dès que 0 ou '' sont des valeurs valables :

js
const quantiteSaisie = 0;
quantiteSaisie || 10     // 10 : 0 est falsy, la valeur par défaut l'écrase (bug)
quantiteSaisie ?? 10     // 0  : ?? ne remplace que null et undefined
'' || 'sans nom'         // 'sans nom'
'' ?? 'sans nom'         // ''

i++ renvoie la valeur avant l'incrément, ++i la valeur après : avec let i = 5, console.log(i++, i, ++i) affiche 5 6 7. Pour éviter toute confusion, écris l'incrément sur sa propre ligne.

Fil rouge : une pièce en variables

Avant de ranger les pièces dans un objet, décris-en une avec des variables et calcule sa valeur en stock :

js
const ref = 'RAM-16';
const nom = 'Barrette DDR4 16 Go';
let quantite = 3;
const seuil = 4;
const prix = 38.5;

quantite += 2;                         // réception de 2 barrettes
const valeur = quantite * prix;
const enAlerte = quantite <= seuil;

console.log(`${ref} (${nom}) : ${quantite} en stock, valeur ${valeur.toFixed(2)} €`);
console.log(`Alerte : ${enAlerte}`);
text
RAM-16 (Barrette DDR4 16 Go) : 5 en stock, valeur 192.50 €
Alerte : false

toFixed(2) donne un point décimal : l'affichage français propre, avec virgule et espace, viendra avec Intl au chapitre 6.

Exercices

Exercice 1 sur 4 Prédire les types et les valeurs Réussi À revoir

Sans exécuter le code, donne le résultat de chaque expression, puis vérifie dans la console.

  1. typeof '12'
  2. '12' + 3
  3. '12' - 3
  4. Number('')
  5. Number('12,5')
  6. typeof null
  7. 0 ?? 5
  8. 0 || 5
  9. '10' < '9'
  10. NaN === NaN
Voir la réponseMasquer la réponse de l'exercice 1
  1. 'string' : les guillemets en font une chaîne.
  2. '123' : + avec une chaîne concatène.
  3. 9 : - force la conversion en nombre.
  4. 0 : la chaîne vide devient 0, un piège pour les champs vides.
  5. NaN : Number ne comprend pas la virgule.
  6. 'object' : erreur historique du langage.
  7. 0 : ?? ne remplace que null et undefined.
  8. 5 : 0 est falsy.
  9. true : comparaison de chaînes caractère par caractère, '1' vient avant '9'.
  10. false : NaN n'est égal à rien ; teste-le avec Number.isNaN.

Tu avais trouvé ?

Exercice 2 sur 4 Corriger le calcul du panier Réussi À revoir

Ce code doit afficher le total d'une commande de pièces : 2 chargeurs à 24 €, sans frais de port. Il affiche Total : 480 €. Trouve la cause, puis corrige le code en appliquant les bonnes pratiques du chapitre.

js
var quantite = champQuantite.value;   // '2'
var prix = 24;
var fraisPort = '0';
var total = quantite * prix + fraisPort;
console.log('Total : ' + total + ' €');
Voir la réponseMasquer la réponse de l'exercice 2

quantite * prix donne bien 48, car * convertit la chaîne '2' en nombre. Mais fraisPort est une chaîne : 48 + '0' concatène et donne '480'. Le calcul ne marchait que par chance pour la multiplication.

Corrections : convertir chaque saisie en nombre dès sa lecture, pour ne jamais dépendre des conversions automatiques, et remplacer var par const.

js
const quantite = Number(champQuantite.value);
const prix = 24;
const fraisPort = Number('0');
const total = quantite * prix + fraisPort;
console.log(`Total : ${total} €`);   // Total : 48 €

Tu avais trouvé ?

Exercice 3 sur 4 Valeur par défaut Réussi À revoir

Une pièce peut avoir un champ remise (en pourcentage) qui vaut 0, 10, ou qui est absent (undefined). On écrit const taux = remise || 5; pour appliquer 5 % par défaut. Quelle valeur prend taux pour chacun des trois cas ? Quelle écriture faut-il utiliser ?

Voir la réponseMasquer la réponse de l'exercice 3

Avec || : remise = 0 donne 5 (bug : une remise nulle volontaire est remplacée), remise = 10 donne 10, remise = undefined donne 5.

Il faut const taux = remise ?? 5; : 0 donne 0, 10 donne 10, undefined donne 5.

Tu avais trouvé ?

Exercice 4 sur 4 Statut d'une pièce Réussi À revoir

Avec les variables quantite et seuil d'une pièce, écris les expressions booléennes enRupture (plus aucune unité), enAlerte (quantité inférieure ou égale au seuil) et aCommander (en alerte mais pas en rupture). Donne leur valeur pour CHG-65 (quantité 0, seuil 2) et pour ECR-156 (quantité 2, seuil 1).

Voir la réponseMasquer la réponse de l'exercice 4
js
const enRupture = quantite === 0;
const enAlerte = quantite <= seuil;
const aCommander = enAlerte && !enRupture;
  • CHG-65 : enRupture vaut true, enAlerte vaut true (0 ≤ 2), aCommander vaut false.
  • ECR-156 : enRupture vaut false, enAlerte vaut false (2 > 1), aCommander vaut false.

Tu avais trouvé ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Conditions et boucles : if, switch, for…of, whileRevoir le sommaire du cours