Javascript • Système de types • Valeurs primitives
Introduction
Section intitulée « Introduction »Dans cette série d’articles, nous faisons un focus sur les fonctionnalités de base de Javascript.
Cet article concerne le système de types proposé par Javascript. Nous allons détailler maintenant les types primitifs.
Système de types en Javascript
Section intitulée « Système de types en Javascript »Typage dynamique
Section intitulée « Typage dynamique »Javascript possède un typage dynamique. Qu’est-ce-que cela signifie exactement ?
🔑 Nous ne déclarons pas le type d’une variable avant de l’utiliser.
🔑 Le type d’une variable est déterminé à l’exécution (et pas à la compilation).
🔑 Le type d’une variable peut changer pendant sa durée de vie.
// → toto est une chaine de caractères (string)let toto = "text";
// → toto est maintenant un nombre (number)toto = 69;
// → toto est maintenant un booléen (boolean)toto = true;Typage faible
Section intitulée « Typage faible »Javascript est également faiblement typé. Il permet ainsi des conversions implicites de type.
const oneTwoThree = 123; // numberconst fourFive = "45"; // stringconst result = oneTwoThree + fourFive; // stringconsole.log(result); // ← "12345"Valeurs primitives
Section intitulée « Valeurs primitives »Le typage Javascript est divisé en deux mondes : les types de valeurs primitives (ou types primitifs) et les types objet. Le premier ensemble inclus :
- le type nul - null ;
- le type indéfini - undefined ;
- le type booléen - boolean ;
- le type nombre - number ;
- le type chaine de caractères - string ;
- le type symbole - symbol.
Les valeurs primitives sont immuables. C’est-à-dire qu’une valeur primitive ne peut pas être modifiée après sa création. Il est bien entendu possible d’affecter une autre valeur primitive à une variable.
Les types primitifs sont des types valeur (value type) : une variable d’un type primitif contient directement la valeur.
L’opérateur typeof nous permet de connaitre le type actuel d’une variable.
let toto = "text";console.log(typeof toto); // ← "string"
toto = 69;console.log(typeof toto); // ← "number"
toto = true;console.log(typeof toto); // ← "boolean"Object wrapper
Section intitulée « Object wrapper »Lorsque nous affectons une valeur primitive à une variable, Javascript lui associe l’objet wrapper correspondant à son type
(à l’exception de null et undefined).
// → twelve est un nombre (number), l'objet Number est appliqué à twelveconst twelve = 12;
// → Nous avons accès aux méthodes d'instance de Number// .toExponential(), .toFixed(), .toString(), etc.const stringTwelve = twelve.toString(); // "12"| Type | typeof | Object wrapper |
|---|---|---|
| null | ”object” | - |
| undefined | ”undefined” | - |
| boolean | ”boolean” | Boolean |
| number | ”number” | Number |
| string | ”string” | String |
| symbol | ”symbol” | Symbol |
Conversion explicite de type
Section intitulée « Conversion explicite de type »Chaque object wrapper nous permet de faire une conversion explicite de type.
const falsyNumber = Boolean(0); // → falseconst truthyString = Boolean("abc"); // → trueconst stringifiedNumber = String(123); // → "123"const numberedString = Number("456"); // → 456null & undefined
Section intitulée « null & undefined »Le type null ne possède qu’une seule valeur : null.
La valeur null représente l’absence intentionnelle de valeur.
Nous pouvons aussi interpréter null par : « aucun objet ».
null est un mot-clef, ainsi une variable ne peut pas être nommée null.
null est une valeur falsy,
c’est-à-dire qu’elle équivaut à false pour les opérations booléennes.
undefined
Section intitulée « undefined »Le type undefined ne possède qu’une seule valeur : undefined.
Une variable déclarée et sans affectation sera undefined.
let toto;console.log(toto); // ← undefinedUne fonction qui ne retourne aucune valeur retourne undefined.
// → La fonction log ne retourne aucune valeurconst log = (text) => { console.log(text);};
// → Un avertissement peut apparaitre pour cette instruction :// "Void function return value is used"const logResult = log("This is Sparta!");
console.log(logResult); // ← undefinedundefined est une valeur falsy,
c’est-à-dire qu’elle équivaut à false pour les opérations booléennes.
Différences et points communs
Section intitulée « Différences et points communs »Nous allons voir ensemble quelques exemples de différences et points communs entre null et undefined.
console.log(typeof null); // ← "object"console.log(typeof undefined); // ← "undefined"console.log(undefined === undefined); // ← trueconsole.log(null === null); // ← trueconsole.log(null === undefined); // ← falseconsole.log(null == undefined); // ← trueconsole.log(!null); // ← trueconsole.log(!undefined); // ← trueconsole.log(!!null); // ← falseconsole.log(!!undefined); // ← falseconsole.log(Number.isNaN(1 + null)); // ← falseconsole.log(Number.isNaN(1 + undefined)); // ← truenull et undefined sont des valeurs nullish.
Ainsi, elles ont le même comportement sur les opérateurs de coalescence.
Nullish coalescing operator (??)
Section intitulée « Nullish coalescing operator (??) »L’opérateur ?? renvoie l’opérateur de droite si l’opérande de gauche est nullish.
const notNull = "Non nul";const nullish = undefined;console.log(notNull ?? "Défaut"); // ← "Non nul"console.log(nullish ?? "Défaut"); // ← "Défaut"Nullish coalescing assignment (??=)
Section intitulée « Nullish coalescing assignment (??=) »L’opérateur ??= évalue l’opérande de droite et l’attribue à gauche si l’opérande de gauche est nullish.
const person = { firstName: null, lastName: "Johnson" };person.firstName ??= "(unknown)";person.lastName ??= "(unknown)";
console.log(person); // ← Object { firstName: "(unknown)", lastName: "Johnson" }Optional chaining (?.)
Section intitulée « Optional chaining (?.) »L’opérateur ?. est similaire à l’opérateur de chainage .,
à ceci près qu’au lieu de causer une erreur si une référence est nullish,
l’évaluation s’arrête et retourne undefined.
// Vide la console, sans erreurwindow.console.clear();
// → Uncaught TypeError: can't access property "clear", window.konsole is undefinedwindow.konsole.clear();
window.konsole?.clear(); // ← undefinedLe type boolean possède deux valeurs : false et true.
L’object wrapper associé à boolean est :
Boolean.
Opérateurs
Section intitulée « Opérateurs »Les opérateurs de comparaison
==,
===,
!=,
!==,
<,
<=,
>,
>=
retournent un boolean.
Les opérateurs logiques
AND (&&),
OR (||),
NOT (!)
permettent d’effectuer des opérations sur les boolean.
Falsy & Truthy
Section intitulée « Falsy & Truthy »Lorsque nous utilisons ces opérateurs, les valeurs non booléennes sont implicitement converties en boolean.
Ainsi certaines valeurs sont converties en false, alors que d’autres sont converties en true.
Nous parlons alors de valeurs falsy
et de valeurs truthy.
Voici quelques valeurs falsy :
falsenullundefined0,+0,-0NaN'',""
Voici quelques valeurs truthy :
true{}[]-3.14,-1,1,3.14-Infinity,Infinitynew Date()"false","0","a"
Le type number permet de stocker à la fois des nombres entiers et des nombres à virgule flottante.
L’object wrapper associé à number est :
Number.
Nombre à virgule flottante
Section intitulée « Nombre à virgule flottante »Les nombres à virgule flottante sont représentés sur 64 bits. Cette représentation permet de stocker des valeurs entre 2-1074 [Number.MIN_VALUE] et 2+1074 [Number.MAX_VALUE], aussi bien négatifs que positifs.
Nombre entier
Section intitulée « Nombre entier »Les nombres entiers peuvent être stockés de façon sûre entre -(253 − 1) [Number.MIN_SAFE_INTEGER] et +(253 − 1) [Number.MAX_SAFE_INTEGER]. En dehors de cet interval, un nombre entier est converti en nombre à virgule flottante, perdant ainsi de sa précision. Nous pouvons utiliser la méthode Number.isSafeInteger() pour savoir si un entier possède une valeur fiable ou pas.
Si un nombre obtient une valeur en dehors des limites alors les conversions suivantes sont appliquées :
- un nombre positif plus grand que +Number.MAX_VALUE est converti en Number.POSITIVE_INFINITY
- un nombre positif plus petit que Number.MIN_VALUE
est converti en
+0 - un nombre négatif plus petit que Number.MIN_VALUE
est converti en
-0 - un nombre négatif plus grand que -Number.MAX_VALUE est converti en Number.NEGATIVE_INFINITY
NaN (Not A Number)
est une valeur spéciale indiquant que la valeur n’est pas un nombre.
Voici quelques exemples d’opérations qui retourne NaN :
- conversion implicite ou explicite impossible vers
number:parseInt("blabla"),Number(undefined),Math.abs(undefined) - opération mathématique qui ne retourne pas un nombre réel :
Math.sqrt(-1) - opération indéterminée avec
Infinity:0 * Infinity,Infinity / Infinity,Infinity - Infinity - opération implicite ou explicite avec
Nan:5 * NaN,NaN - 4,3 * "blabla"
Il est possible de vérifier si un nombre est NaN Number.isNaN()
ou isNaN().
console.log(NaN === NaN); // ← falseconsole.log(Number.NaN === NaN); // ← falseconsole.log(Number.NaN); // ← NaNconsole.log(isNaN(NaN)); // ← trueconsole.log(Number.isNaN(NaN)); // ← trueconsole.log(isNaN(-0)); // ← falseconsole.log(isNaN(-3.14)); // ← falseconsole.log(isNaN(19)); // ← falseLe type string permet de stocker une chaine de caractères
encodée en UTF-16.
L’object wrapper associé à string est :
String.
Valeur littérale
Section intitulée « Valeur littérale »Un texte (ou valeur littérale) peut être declaré :
- entre simples quotes : ‘Maître Corbeau, sur un arbre perché, tenait en son bec un fromage.’ ;
- entre doubles quotes : “Maître Renard, par l’odeur alléché, lui tint à peu près ce langage :” ;
- entre accents graves (backtick) : `Et bonjour, Monsieur du Corbeau. Que vous êtes joli ! Que vous me semblez beau !`.
Gabarit de littéral
Section intitulée « Gabarit de littéral »Un texte entre accents graves permet de définir un gabarit de littéral (template literal).
Il est ainsi possible d’interpoler des expressions en utilisant ${}.
const animals = ["Lièvre", "Tortue"];const fable = `Rien ne sert de courir ; il faut partir à point.Le ${animals[0]} et la ${animals[1]} en sont un témoignage.`;
// → Rien ne sert de courir ; il faut partir à point.// Le Lièvre et la Tortue en sont un témoignage.console.log(fable);Opérateurs
Section intitulée « Opérateurs »Nous pouvons concaténer des chaines de caractères avec l’opérateur +.
const grasshopper = "La Cigale";const ant = "La Fourmi";console.log(grasshopper + " et " + ant); // ← La Cigale et La FourmiNous pouvons faire un combo concaténation + affectation avec l’opérateur +=.
let fable = "Le Corbeau";fable += " et Le Renard";console.log(fable); // ← Le Corbeau et Le RenardConclusion
Section intitulée « Conclusion »Javascript propose un typage dynamique et faible, nous évitant de trop nous soucier du type des données que nous manipulons.
Nous avons vu le premier ensemble de types : les types de valeurs primitives.
Dans l’article suivant, nous nous concentrerons sur les types objet.