Retour au cours

frontend / javascript

Variables, types et opérateurs

Leçon 11 exercice

Explication

Un peu d'histoire

JavaScript est créé par Brendan Eich chez Netscape, en seulement 10 jours, en mai 1995. Le langage s'appelle d'abord Mocha, puis LiveScript, avant d'être renommé JavaScript pour des raisons purement marketing : Java était très à la mode à l'époque, mais les deux langages n'ont techniquement presque rien en commun. Standardisé en 1997 sous le nom officiel ECMAScript, JavaScript est longtemps resté vu comme un langage "de bricolage", réservé à de petites animations dans le navigateur.

Ce statut change radicalement dans les années 2000-2010, avec l'arrivée de moteurs d'exécution beaucoup plus rapides (comme V8, créé par Google pour Chrome en 2008) et surtout avec Node.js (2009), qui permet d'exécuter du JavaScript en dehors du navigateur, côté serveur.

Pourquoi apprendre JavaScript aujourd'hui

JavaScript est le seul langage de programmation nativement compris par tous les navigateurs web : impossible de faire du développement frontend moderne sans le connaître, que ce soit en JavaScript pur ou via un framework comme React ou Vue. Grâce à Node.js, le même langage sert aussi côté serveur, ce qui permet à un développeur de couvrir un projet entier (frontend et backend) avec une seule base de compétences. Son écosystème de paquets (npm) est le plus grand au monde, et la demande de développeurs JavaScript reste extrêmement élevée.

Ce que vous allez apprendre

  • Déclarer une variable avec let et const, et expliquer pourquoi var est à éviter
  • Justifier pourquoi const objet = {} n'empêche pas de faire objet.prop = "x"
  • Distinguer == et ===, et utiliser === par réflexe
  • Reconnaître les pièges classiques de la coercion de type ("5" + 3, [] + [])
  • Expliquer pourquoi 0.1 + 0.2 !== 0.3 sans y voir un bug du langage
  • Lire correctement typeof null sans se faire piéger en entretien ou en code review

Dans quel contexte ?

Imagine une revue de code sur une pull request qui corrige un bug de panier e-commerce : le total affiché est "1053" au lieu de 105, parce que la fonction calculerTotal(prixUnitaire, quantite) reçoit parfois quantite sous forme de chaîne de caractères venue d'un champ de formulaire HTML jamais converti en nombre. La ligne total = total + prix a silencieusement concaténé deux valeurs au lieu de les additionner. Comprendre la coercion de type et le bon usage de === permet de repérer ce genre de bug avant même l'ouverture de la pull request.

Prérequis

Aucune connaissance de JavaScript n'est nécessaire pour cette leçon : c'est le tout premier contact avec la syntaxe du langage. Un navigateur avec une console développeur (touche F12) suffit pour tester chaque exemple.

1. Donner un nom à une valeur

Avant d'aller plus loin, il faut un endroit où ranger l'information : une variable est une étiquette qu'on colle sur une valeur pour pouvoir la réutiliser. Écrire let age = 30 revient à dire "retiens 30 sous le nom age", rien de plus compliqué pour commencer.

2. Trois façons de déclarer, une seule vraiment recommandée

JavaScript propose var, let et const. let et const sont "block-scoped" : ils n'existent que dans les accolades où ils sont créés. var, plus ancien, déborde de son bloc et provoque des bugs difficiles à tracer — à éviter dans du code moderne.

Mot-cléPortéeRedéclarableComportement avant sa ligne
varFonction entièreOuiVaut undefined (hissée)
letBloc { }NonErreur si utilisée avant (zone morte)
constBloc { }NonErreur si utilisée avant (zone morte)

3. const ne verrouille que l'étiquette

Piège fréquent chez les débutants : const ne rend pas la valeur immuable, seulement la variable non réassignable. Un objet déclaré avec const reste parfaitement modifiable de l'intérieur (objet.propriete = ...) ; seule une réaffectation complète (objet = {}) est interdite.

4. Un typage dynamique... et faible

Une fois les déclarations comprises, vient une particularité du langage : une variable peut changer de type en cours de route (typage dynamique), et JavaScript convertit même silencieusement les types entre eux quand c'est possible (typage faible, ou "coercion"). C'est pratique en apparence, jusqu'à ce que "5" + 3 donne "53" au lieu de 8.

5. Toujours comparer avec ===

Cette coercion silencieuse explique pourquoi == est dangereux : il convertit les types avant de comparer, avec des résultats parfois absurdes (null == undefined vaut true). === compare sans jamais convertir : c'est le seul opérateur d'égalité à utiliser par réflexe.

Piège fréquent

null == undefined vaut true mais null === undefined vaut false. Cette exception ne justifie pas d'utiliser == ailleurs : gardez === comme réflexe partout dans votre code, sans exception, pour ne jamais avoir à vous souvenir des cas particuliers.

6. Une limite universelle : les nombres flottants

Autre surprise classique une fois qu'on manipule des nombres : 0.1 + 0.2 !== 0.3. Ce n'est pas un bug de JavaScript, mais une conséquence de la norme IEEE 754 partagée par presque tous les langages : les flottants ne peuvent pas représenter exactement toutes les valeurs décimales.

Astuce

Pour comparer deux nombres flottants sans tomber dans ce piège, ne testez jamais a === b directement sur un résultat de calcul : vérifiez plutôt que Math.abs(a - b) < Number.EPSILON, ou une tolérance adaptée à votre cas d'usage (par exemple 0.01 pour un montant en euros).

7. Le dernier piège avant de continuer

Pour finir cette première leçon, retenez que typeof null renvoie "object" — une erreur du tout premier JavaScript, jamais corrigée pour ne pas casser le code existant. Ces bases (déclaration, typage, comparaison) reviendront dans absolument toutes les leçons suivantes : prenez le temps de bien les stabiliser avant d'avancer.

Commandes & code

Variables, types et opérateurs

Les fondations du langage : déclarer, typer, comparer.

js
// let / const : declarations modernes (block-scoped)
let age = 30;
const nom = "Alice";       // const : la REFERENCE est constante, pas le contenu
age = 31;                    // OK, let est reassignable

// var : ancienne declaration, function-scoped (a eviter dans du code moderne)
var ancienneVariable = "eviter var";

// const avec un objet : le contenu reste mutable
const utilisateur = { nom: "Bob" };
utilisateur.nom = "Robert";      // OK : on modifie une propriete, pas la reference
// utilisateur = {};              // TypeError : reassignation interdite

// Types primitifs
const chaine = "texte";
const nombre = 42;
const flottant = 3.14;
const booleen = true;
const indefini = undefined;
const nul = null;
const symbole = Symbol("id");
const grandEntier = 9007199254740993n;    // BigInt : au-dela de Number.MAX_SAFE_INTEGER

console.log(typeof chaine, typeof nombre, typeof booleen, typeof indefini);
console.log(typeof nul);          // "object" -- bug historique connu de JS, a retenir
console.log(typeof grandEntier);   // "bigint"

// Egalite stricte (===) vs egalite faible (==)
console.log(1 === "1");     // false : types differents, pas de conversion
console.log(1 == "1");       // true : conversion implicite (coercion) -- a EVITER
console.log(null == undefined);   // true (cas special)
console.log(null === undefined);   // false

// Operateurs de coalescence et chainage optionnel (ES2020)
const config = { theme: null };
const theme = config.theme ?? "clair";        // ?? : seulement si null/undefined (pas 0 ou "")
const themeOr = config.theme || "clair";       // || : si falsy (0, "", null, undefined, NaN)

const utilisateurProfond = { profil: null };
const ville = utilisateurProfond.profil?.adresse?.ville ?? "inconnue";   // optional chaining

// Operateurs numeriques et particularites du type Number (IEEE 754 double precision)
console.log(0.1 + 0.2);              // 0.30000000000000004 : imprecision des flottants
console.log(0.1 + 0.2 === 0.3);       // false
console.log(Number.isNaN(NaN));        // true : methode fiable (contrairement a isNaN global)
console.log(10 % 3);                     // 1 : modulo
console.log(2 ** 10);                     // 1024 : exponentiation

// Coercion de type implicite : sources de bugs classiques
console.log("5" + 3);          // "53" : + avec une chaine concatene
console.log("5" - 3);           // 2 : - force la conversion numerique
console.log([] + []);            // "" : conversion en chaine des tableaux
console.log([] + {});             // "[object Object]"
console.log(1 + true);             // 2 : true converti en 1

// Template literals : interpolation et multi-lignes
const prenom = "Ana";
console.log(`Bonjour ${prenom}, tu as ${age} ans.`);
const multiligne = `Ligne 1
Ligne 2`;

// Destructuring des le declaratif
const { nom: nomUtilisateur, age: ageUtilisateur = 18 } = { nom: "Cy" };
const [premier, second] = [1, 2, 3];

Résumé

  • const fige la référence, pas le contenu ; préférer let/const à var.
  • === compare sans conversion de type, == applique une coercion souvent source de bugs.
  • ?? ne retombe sur le défaut que pour null/undefined, contrairement à ||.
  • Les flottants JS suivent IEEE 754 : 0.1 + 0.2 !== 0.3 est normal, pas un bug.

Exercices pratiques

1 disponible
1

Mission : traquer le bug du panier e-commerce

Objectif : Identifier et corriger un bug de coercion de type dans un calcul de panier, puis justifier chaque choix par écrit.

Contexte

Sur la boutique en ligne de Technologik, un client signale que son panier affiche un total de "105033" au lieu de 1083. Le code suspect ressemble à ceci :

js
function calculerTotal(prixUnitaire, quantite) {
  let total = 0;
  total = total + prixUnitaire * quantite;
  return total;
}
console.log(calculerTotal(361, "3"));

La quantite vient d'un champ de formulaire HTML, donc toujours d'une chaîne de caractères. Tu dois comprendre précisément ce que fait la coercion ici, corriger le code, puis expliquer le principe général pour que ce bug ne revienne jamais dans une autre fonction.

Résoudre l’exercice →