📍 Le guide du parcours : JavaScript moderne : le guide complet
Ce tutoriel ouvre la série consacrée au JavaScript moderne. Pour la vue d’ensemble et l’ordre conseillé, lisez d’abord le guide.
Introduction
Vous tapez "3" + 1 dans la console et vous obtenez "31". Vous tapez "3" - 1 et vous obtenez 2. Le même opérande, deux comportements opposés : bienvenue dans le monde des types et de la coercition en JavaScript. Loin d’être des bizarreries à craindre, ces règles sont parfaitement logiques une fois qu’on a compris les sept types primitifs du langage et la manière dont il convertit les valeurs. C’est précisément ce que vous saurez faire à la fin de ce tutoriel : prédire le type d’une valeur, savoir quand JavaScript la convertit, et écrire des comparaisons qui ne réservent aucune surprise.
🎯 Ce que vous allez apprendre
- Distinguer les sept types primitifs et le type objet, et reconnaître chacun avec
typeof. - Comprendre la différence entre
nulletundefined, et pourquoitypeof nullvaut"object". - Anticiper la coercition implicite et choisir entre
===et==en connaissance de cause. - Manipuler correctement les nombres, les chaînes et les booléens, y compris les cas limites comme
NaN. - Valider les champs d’un objet en testant leur type, sur un cas réel.
🛠️ Ce que vous allez construire
Vous allez modéliser la donnée centrale de l’application CarnetTâches : l’objet tâche. Au passage, vous écrirez une petite fonction decrireType() qui révèle le vrai type de n’importe quelle valeur, puis un validateur qui refuse une tâche mal formée. Le résultat est une base de données en mémoire propre, sur laquelle tous les tutoriels suivants s’appuieront.
Prérequis
- Un navigateur récent (Chrome, Firefox, Edge) et sa console de développement (touche F12, onglet « Console »).
- Aucune installation : tout le code de ce tutoriel s’exécute directement dans la console.
- Niveau débutant. Test express : si vous savez ouvrir la console et y taper
1 + 1, vous êtes prêt. - ⏱️ Temps estimé : ~35 minutes.
Étape 1 — Reconnaître les types primitifs
Avant de modéliser quoi que ce soit, il faut savoir avec quelles briques on travaille. JavaScript définit huit types : sept primitifs et le type objet. Les primitifs représentent des valeurs simples et immuables. Les voici, avec une valeur d’exemple pour chacun. L’opérateur typeof renvoie une chaîne décrivant le type d’une valeur ; c’est notre premier outil d’inspection.
typeof undefined; // "undefined" — pas de valeur assignée
typeof null; // "object" — bug historique, voir plus bas
typeof true; // "boolean" — vrai ou faux
typeof 42; // "number" — tous les nombres (entiers et décimaux)
typeof 9007199254740993n;// "bigint" — entiers de précision arbitraire
typeof "tâche"; // "string" — texte
typeof Symbol("id"); // "symbol" — identifiant unique
typeof { titre: "x" }; // "object" — objets, tableaux, dates...
typeof function () {}; // "function" — cas particulier, c'est un objet appelable
Notez deux pièges immédiats. D’abord, typeof null ne renvoie pas "null" mais "object" : c’est une erreur des tout premiers jours du langage, conservée pour ne pas casser le code existant. Pour tester une valeur nulle, comparez-la directement : valeur === null. Ensuite, typeof sur une fonction renvoie "function" alors qu’une fonction est techniquement un objet — une commodité bien utile pour savoir si une valeur est appelable.
✅ Point d’étape — Ouvrez votre console et tapez chacune de ces lignes. Vous devez voir exactement les chaînes commentées à droite. Si
typeof nullvous renvoie autre chose que"object", c’est que vous avez fait une faute de frappe.
Étape 2 — Comprendre null et undefined
Ces deux valeurs expriment l’absence, mais pas de la même façon, et confondre les deux est une source classique de bugs. undefined signifie « cette variable existe mais n’a jamais reçu de valeur » — c’est ce que JavaScript met par défaut. null signifie « j’ai volontairement mis une absence ici » — c’est une décision du développeur. La distinction compte au moment de modéliser une tâche dont l’échéance n’est pas encore fixée.
let echeance; // déclarée, pas initialisée
console.log(echeance); // undefined
echeance = null; // on affirme : « pas d'échéance pour l'instant »
console.log(echeance); // null
// Conséquence sur les comparaisons :
null == undefined; // true — l'égalité permissive les confond
null === undefined; // false — l'égalité stricte les distingue
typeof undefined; // "undefined"
typeof null; // "object"
En pratique, choisissez une convention et tenez-vous-y. Pour CarnetTâches, une échéance absente sera représentée par null : c’est une absence assumée, pas un oubli. Tester tache.echeance === null est alors sans ambiguïté.
Étape 3 — Les nombres et le cas de NaN
JavaScript n’a qu’un seul type pour les entiers et les décimaux : number, un flottant 64 bits. Cela simplifie l’écriture mais impose de connaître ses limites. La plus connue est NaN (Not a Number), la valeur renvoyée quand un calcul numérique échoue, par exemple en multipliant un texte non numérique.
Number("12"); // 12 — conversion réussie
Number("douze"); // NaN — échec de conversion
0.1 + 0.2; // 0.30000000000000004 — arrondi des flottants
// NaN a une propriété déroutante : il n'est égal à rien, pas même à lui-même
NaN === NaN; // false
Number.isNaN(NaN); // true — la bonne façon de tester
Number.isNaN("texte"); // false — ne convertit pas, contrairement au global isNaN()
// Bornes de sécurité des entiers
Number.MAX_SAFE_INTEGER; // 9007199254740991
Deux réflexes à retenir. Pour tester si une valeur est NaN, utilisez Number.isNaN() et jamais une comparaison directe, puisque NaN n’est égal à rien. Et pour des entiers dépassant Number.MAX_SAFE_INTEGER, basculez sur le type bigint en suffixant le nombre d’un n : 9007199254740993n. Pour les priorités de nos tâches (1, 2 ou 3), le type number classique suffit amplement.
✅ Point d’étape — Tapez
0.1 + 0.2 === 0.3dans la console. Vous devez obtenirfalse. C’est normal : les flottants ne représentent pas exactement certains décimaux. Pour comparer des montants, on travaille en plus petites unités entières ou on arrondit explicitement.
Étape 4 — La coercition, ou la conversion automatique
Le cœur des surprises de JavaScript se trouve ici. Comme le langage est à typage dynamique, il convertit volontiers une valeur d’un type vers un autre quand le contexte l’exige. On parle de coercition. Comprendre ses règles, c’est passer de « JavaScript fait n’importe quoi » à « JavaScript suit des règles que je connais ».
L’opérateur + est le plus piégeux car il sert à la fois à additionner des nombres et à concaténer des chaînes. Dès qu’un de ses opérandes est une chaîne, il bascule en mode concaténation. Les autres opérateurs arithmétiques (-, *, /) n’ont pas cette ambiguïté : ils convertissent toujours vers number.
"3" + 1; // "31" — concaténation : 1 devient "1"
"3" - 1; // 2 — soustraction : "3" devient 3
true + 1; // 2 — true vaut 1 en numérique
[] + []; // "" — deux tableaux convertis en chaînes vides
"5" * "2"; // 10 — les deux chaînes deviennent des nombres
// Coercition vers booléen dans un contexte conditionnel
Boolean(""); // false — chaîne vide
Boolean("0"); // true — chaîne non vide, attention !
Boolean(0); // false
Boolean(null); // false
Retenez la liste des valeurs « fausses » (falsy) : false, 0, -0, 0n, "", null, undefined et NaN. Tout le reste est « vrai » (truthy), y compris la chaîne "0" et le tableau vide []. C’est pourquoi if (tache.titre) est un test pratique pour « le titre n’est pas vide », à condition de se souvenir que "0" y serait considéré comme rempli.
Étape 5 — Égalité stricte contre égalité permissive
Vous disposez maintenant de tout pour comprendre la règle d’or des comparaisons. L’égalité permissive == applique la coercition avant de comparer, ce qui produit des résultats que personne ne devine de tête. L’égalité stricte === ne convertit rien : elle exige même type et même valeur. Dans la quasi-totalité des cas, c’est === qu’il faut utiliser.
0 == ""; // true — coercition vers nombre
0 == "0"; // true
"" == "0"; // false — déroutant : == n'est pas transitif !
false == "false"; // false — "false" devient NaN
0 === ""; // false — types différents, pas de conversion
1 === 1; // true
// Le cas particulier que === ne gère pas : NaN et -0
NaN === NaN; // false
Object.is(NaN, NaN); // true — Object.is distingue ces cas limites
Object.is(-0, 0); // false
L’exemple 0 == "" qui vaut true alors que "" == "0" vaut false montre que l’égalité permissive n’est même pas transitive. C’est ingérable mentalement. Adoptez === comme réflexe ; la seule exception courante et défendable est valeur == null, qui teste d’un coup null et undefined — pratique, mais à utiliser en connaissance de cause. Pour les cas limites NaN et -0, Object.is() donne le résultat « intuitif » que === ne fournit pas.
✅ Point d’étape — Prédisez le résultat de
"" == "0"avant de l’exécuter, puis vérifiez. Si vous aviez anticipéfalseen expliquant pourquoi, vous avez compris la coercition.
Étape 6 — Modéliser et valider une tâche
Assemblons tout. Une tâche de CarnetTâches est un objet, et chacun de ses champs a un type attendu. On va écrire un validateur qui vérifie ces types et rejette toute tâche mal formée — exactement le genre de garde-fou qui évite des bugs en cascade plus tard.
function decrireType(valeur) {
if (valeur === null) return "null";
if (Array.isArray(valeur)) return "array"; // typeof [] vaut "object", on précise
return typeof valeur;
}
function validerTache(t) {
const erreurs = [];
if (decrireType(t.titre) !== "string" || t.titre.trim() === "")
erreurs.push("titre manquant");
if (decrireType(t.fait) !== "boolean")
erreurs.push("le champ fait doit être un booléen");
if (decrireType(t.priorite) !== "number" || ![1, 2, 3].includes(t.priorite))
erreurs.push("priorité invalide (1, 2 ou 3)");
if (decrireType(t.etiquettes) !== "array")
erreurs.push("etiquettes doit être un tableau");
// echeance : soit une chaîne ISO, soit null (absence assumée)
if (t.echeance !== null && decrireType(t.echeance) !== "string")
erreurs.push("echeance doit être une chaîne ou null");
return erreurs;
}
const bonne = { titre: "Réviser", fait: false, priorite: 2, etiquettes: ["étude"], echeance: null };
const mauvaise = { titre: "", fait: "oui", priorite: 9, etiquettes: "étude", echeance: 12345 };
console.log(validerTache(bonne)); // [] → valide
console.log(validerTache(mauvaise));// ["titre manquant", "le champ fait doit être un booléen", ...]
La fonction decrireType() corrige les deux faiblesses de typeof vues plus haut : elle distingue null et les tableaux, qui se cachent tous deux derrière "object". Le validateur, lui, renvoie une liste d’erreurs vide si la tâche est correcte. C’est un patron très répandu : on accumule les problèmes plutôt que de s’arrêter au premier, ce qui donne un retour complet à l’utilisateur.
Étape 7 — Vérification finale
Pour prouver que tout fonctionne de bout en bout, créez une petite liste en mémoire et filtrez les tâches valides. C’est l’embryon de la base de données de CarnetTâches.
const candidates = [
{ titre: "Réviser", fait: false, priorite: 2, etiquettes: ["étude"], echeance: null },
{ titre: "", fait: false, priorite: 1, etiquettes: [], echeance: null }, // titre vide
{ titre: "Lire la doc", fait: true, priorite: 3, etiquettes: ["lecture"], echeance: "2026-06-20" }
];
const valides = candidates.filter(t => validerTache(t).length === 0);
console.log(valides.length); // 2 — la tâche au titre vide est écartée
Vous devez voir 2 : la tâche au titre vide est rejetée, les deux autres passent. Vous avez maintenant une donnée propre, typée et validée. C’est le socle sur lequel le tutoriel suivant construira des fonctions.
🐞 Pièges fréquents
| Symptôme / erreur | Cause probable | Correctif |
|---|---|---|
typeof t.etiquettes vaut "object" pour un tableau |
typeof ne distingue pas tableaux et objets |
Utiliser Array.isArray() |
NaN === NaN renvoie false |
NaN n’est égal à aucune valeur |
Tester avec Number.isNaN() |
Un test if (valeur) rate la valeur "0" |
"0" est une chaîne non vide, donc truthy |
Comparer explicitement la valeur attendue |
"3" + 1 donne "31" au lieu de 4 |
+ concatène dès qu’un opérande est une chaîne |
Convertir avec Number() avant d’additionner |
Une comparaison == donne un résultat absurde |
Coercition implicite non transitive | Remplacer par === |
🌍 Réalités du terrain
Tout ce tutoriel s’exécute dans la console du navigateur, sans rien installer ni télécharger. C’est un avantage concret quand la connexion est lente ou coûteuse : on peut explorer les types, tester la coercition et déboguer pendant des heures hors ligne, sur n’importe quelle machine, même modeste. Prenez l’habitude d’ouvrir la console pour vérifier une intuition plutôt que de chercher la réponse en ligne — c’est plus rapide et cela ne consomme pas de données.
✅ Récapitulatif
Vous savez désormais reconnaître les sept types primitifs et le type objet, et inspecter une valeur avec typeof tout en connaissant ses deux pièges (null et les tableaux). Vous distinguez null d’undefined, vous testez NaN correctement, et surtout vous anticipez la coercition : vous savez pourquoi "3" + 1 diffère de "3" - 1 et pourquoi on préfère ===. Enfin, vous avez modélisé et validé l’objet tâche de CarnetTâches — la donnée que tout le parcours va manipuler.
🧾 Aide-mémoire
| Élément | Rôle |
|---|---|
typeof x |
Renvoie le type sous forme de chaîne (sauf null → "object") |
Array.isArray(x) |
Teste si x est un tableau |
Number.isNaN(x) |
Teste si x est exactement NaN |
Object.is(a, b) |
Égalité stricte qui gère NaN et -0 |
=== / !== |
Égalité stricte, sans coercition (à privilégier) |
| falsy | false, 0, -0, 0n, "", null, undefined, NaN |
💪 À vous de jouer
Étendez le validateur pour accepter une échéance au format "AAAA-MM-JJ" uniquement (et la rejeter si la chaîne ne correspond pas), tout en continuant d’autoriser null.
Voir une solution
function echeanceValide(valeur) {
if (valeur === null) return true; // absence assumée : autorisée
if (typeof valeur !== "string") return false;
// format AAAA-MM-JJ, puis on vérifie que la date existe vraiment
if (!/^\d{4}-\d{2}-\d{2}$/.test(valeur)) return false;
const d = new Date(valeur);
return !Number.isNaN(d.getTime()); // NaN si date invalide
}
echeanceValide(null); // true
echeanceValide("2026-06-15"); // true
echeanceValide("15/06/2026"); // false — mauvais format
echeanceValide("2026-13-40"); // false — mois et jour impossibles
Tutoriels liés
- Fonctions, portée et closures — la suite logique : transformer ces données avec des fonctions.
- Manipuler le DOM et consommer une API avec fetch — afficher ces tâches dans une page.
Pour aller plus loin
- 🔝 Retour au guide : JavaScript moderne : le guide complet
- MDN — Types et structures de données JavaScript
- Tutoriel suivant : Fonctions, portée et closures
FAQ
Pourquoi typeof null vaut-il "object" ?
C’est un bug des toutes premières versions de JavaScript, conservé depuis pour ne pas casser le code existant. Pour détecter null, comparez directement : valeur === null.
Quand dois-je utiliser bigint plutôt que number ?
Uniquement pour des entiers dépassant Number.MAX_SAFE_INTEGER (environ 9 quadrillions). Pour la quasi-totalité des besoins courants — compteurs, priorités, index — number suffit.
L’égalité permissive == est-elle toujours à proscrire ?
Presque. La seule exception courante et défendable est valeur == null, qui teste null et undefined en une fois. Partout ailleurs, === évite les conversions surprenantes.
Comment convertir proprement une chaîne en nombre ?
Number("12") pour une conversion stricte (renvoie NaN si le texte n’est pas un nombre), ou parseInt/parseFloat si la chaîne contient une unité à ignorer. Vérifiez toujours le résultat avec Number.isNaN().