Cette page a été traduite à partir de l'anglais par la communauté. Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.

View in English Always switch to English

Une réintroduction à JavaScript

Pourquoi une réintroduction ? Parce que JavaScript est connu pour être source d'incompréhensions. Bien que souvent raillé comme étant un simple jouet, derrière sa simplicité désarmante se cachent certaines fonctionnalités de langage très puissantes. JavaScript est maintenant utilisé par un nombre incroyable d'applications de haut rang, ce qui montre qu'une connaissance approfondie de cette technologie est une compétence importante pour toute développeuse ou développeur web ou mobile.

Il peut être utile de commencer avec un aperçu de l'histoire de ce langage. JavaScript a été créé en 1995 par Brendan Eich, alors ingénieur à Netscape. Ce langage est sorti au grand jour pour la première fois avec Netscape 2 au début de l'année 1996. Il était au départ censé s'appeler LiveScript, mais a été renommé par une décision marketing mal avisée dans le but de capitaliser sur la popularité du langage Java de Sun Microsystems, malgré le fait qu'ils n'aient que très peu en commun. Cela n'a jamais cessé d'être une source de confusion.

Quelques mois plus tard, Microsoft a lancé avec Internet Explorer 3 une version du langage globalement compatible, appelée JScript. Quelques mois après, Netscape a soumis le langage à l'Ecma International, une organisation de normalisation européenne, ce qui a permis d'aboutir à la première édition du standard ECMAScript en 1997. Ce standard a reçu une mise à jour importante appelée ECMAScript edition 3 en 1999, et est resté relativement stable depuis. La quatrième édition a été abandonnée suite à des différends portants sur la complexité du langage. De nombreuses sections de la quatrième édition ont été utilisées pour servir de fondation à la cinquième édition d'ECMAScript, publiée en décembre 2009. La sixième édition, qui apporte des nouveautés majeures, a été publiée en juin 2015.

Note : Dans la suite de cet article et à des fins de simplicité, nous utiliserons les termes « JavaScript » et « ECMAScript » pour désigner la même chose.

Contrairement à la plupart des langages de programmation, JavaScript n'a pas de concept d'entrée ou de sortie. Il est conçu pour s'exécuter comme un langage de script dans un environnement hôte, et c'est à cet environnement de fournir des mécanismes de communication avec le monde extérieur. L'environnement hôte le plus commun est un navigateur, mais des interpréteurs JavaScript existent également dans Adobe Acrobat, Photoshop, les images SVG, le moteur de widgets de Yahoo!, et même au sein d'environnements côté serveur tels que Node.js. Cette liste ne se limite pas qu'à ces éléments et on retrouve également JavaScript dans les bases de données NoSQL telles que Apache CouchDB, les ordinateurs embarqués ou encore des environnements de bureaux comme GNOME (l'une des interfaces graphiques les plus populaires des systèmes d'exploitation GNU/Linux), etc.

Aperçu

JavaScript est un langage dynamique multi-paradigme : il dispose de différents types, opérateurs, objets natifs et méthodes. Sa syntaxe s'inspire des langages Java et C et de nombreuses structures de ces langages s'appliquent également à JavaScript. JavaScript permet la programmation orientée objet avec les prototypes (voir l'héritage et la chaîne de prototypes et les classes apparues avec ES6/ES2015). JavaScript permet également la programmation fonctionnelle car ses fonctions sont des objets et on peut donc stocker ces fonctions dans des variables et les transmettre comme n'importe quel objet.

Commençons par nous intéresser aux briques de base de tout langage : les types. Les programmes en JavaScript manipulent des valeurs, et ces valeurs appartiennent toutes à un type. Les types JavaScript sont :

  • Les nombres : Number
  • Les grands entiers (BigInt) : BigInt
  • Les chaînes de caractères : String
  • Les booléens : Boolean
  • Les fonctions : Function
  • Les objets : Object
  • Les symboles : Symbol (apparus avec la sixième édition d'ECMAScript, ES2015)

On aura également undefined et null, qui sont relativement étranges. Les tableaux ou Array permettent d'organiser des séries d'objets au sein d'un même objet. Les dates (Date) et les expressions rationnelles (RegExp) qui sont également des objets nativement disponibles en JavaScript. Afin d'être tout à fait précis, les fonctions sont aussi une sorte particulière d'objets, de sorte que le diagramme de types ressemble plutôt à ceci :

Enfin, il y a également quelques types natifs pour gérer les exceptions : Error. Pour garder une approche simple, nous utiliserons la première de ces listes pour présenter les types.

Les nombres

ECMAScript possède deux types numériques intégrés : Number et BigInt.

Les nombres en JavaScript sont « des valeurs au format IEEE 754 en double précision 64 bits », d'après la spécification. Cela permet de représenter les nombres entre -(2^53 − 1) et 2^53 − 1. Lorsqu'on fait référence (ici ou dans les autres articles) à des entiers, on parle généralement d'une représentation d'un entier avec une valeur de type Number. En effet, les valeurs Number ne sont pas strictement des entiers et il faut donc prendre quelques précautions :

js
console.log(3 / 2); // 1.5 et pas 1
console.log(Math.floor(3 / 2)); // 1

Ainsi, un entier apparent est en fait implicitement un nombre à virgule flottante.

Aussi, faites attention à des choses comme :

js
0.1 + 0.2 == 0.30000000000000004;

Dans la pratique, les valeurs entières sont traitées comme des entiers représentés sur 32 bits (certaines implémentations les stockent même ainsi tant qu'il n'y a pas besoin d'effectuer une opération valide pour un nombre mais pas pour un entier sur 32 bits). Cette représentation peut être importante pour les opérations binaires.

Les opérateurs arithmétiques standards sont gérés, dont l'addition, la soustraction, le reste arithmétique et ainsi de suite. Il existe également un objet natif, qui n'a pas été mentionné jusqu'à présent, appelé Math, qui permet de gérer certaines fonctions et constantes mathématiques plus avancées :

js
Math.sin(3.5);
let circonference = 2 * Math.PI * r;

On peut convertir une chaîne de caractères en un nombre entier à l'aide de la fonction intégrée parseInt(). Elle reçoit la base de conversion comme second paramètre, qui devrait toujours être fourni afin de lever une éventuelle ambiguïté :

js
parseInt("123", 10); // 123
parseInt("010", 10); //10

Si la base n'est pas indiquée, les résultats peuvent être surprenants dans les anciens navigateurs qui datent de 2013 ou avant où les chaînes commençant par 0 pouvaient ne pas être considérées comme exprimées en notation octale. À moins que vous ne soyez certain du format de votre chaîne de caractères, vous pouvez obtenir des résultats surprenants sur ces anciens navigateurs :

js
parseInt("010"); //  8
parseInt("0x10"); // 16

Cela se produit parce que la fonction parseInt() a été implémentée pour traiter la première chaîne comme un nombre octal à cause du zéro initial et la seconde comme une représentation hexadécimale car commençant avec 0x. Une telle notation hexadécimale peut toujours être utilisée mais la notation octale a été retirée.

Si on souhaite convertir un nombre binaire en un entier, il suffit de changer la base :

js
parseInt("11", 2); // 3

De la même manière, vous pouvez traiter les nombres à virgule flottante à l'aide de la fonction intégrée parseFloat(), qui, à la différence de parseInt(), utilise toujours la base 10.

On peut également utiliser l'opérateur unaire + pour convertir des valeurs en nombres :

js
+"42"; // 42
+"010"; // 10
+"0x10"; // 16

Une valeur spéciale appelée NaN (qui signifie « Not a Number », soit « pas un nombre ») est renvoyée si la chaîne est non numérique :

js
parseInt("coucou", 10); // NaN

NaN est « toxique » : si cette valeur est fournie en entrée pour n'importe quelle opération mathématique, le résultat sera également NaN :

js
NaN + 5; // NaN

Cette valeur peut être détectée grâce à la fonction native Number.isNaN() (qui fait exactement ce que son nom indique) :

js
Number.isNaN(NaN); // true
Number.isNaN("bonjour"); // false
Number.isNaN("1"); // false
Number.isNaN(undefined); // false
Number.isNaN({}); // false
Number.isNaN([1]); // false
Number.isNaN([1, 2]); // false

Mais ne testez pas le NaN en utilisant la fonction globale isNaN(), qui a un comportement peu intuitif :

js
isNaN("bonjour"); // true
isNaN("1"); // false
isNaN(undefined); // true
isNaN({}); // true
isNaN([1]); // false
isNaN([1, 2]); // true

JavaScript dispose également de valeur spéciales pour l'infini Infinity et l'infini négatif (-Infinity) :

js
1 / 0; // Infinity
-1 / 0; // -Infinity

Il est possible de tester les valeurs Infinity, -Infinity et NaN à l'aide de la fonction native isFinite() :

js
isFinite(1 / 0); // false
isFinite(-Infinity); // false
isFinite(NaN); // false

Note : Les fonctions parseFloat() et parseInt() traitent une chaîne de caractères jusqu'à ce qu'elles atteignent un caractère qui n'est pas valide pour le format numérique indiqué, puis renvoient le nombre traité jusqu'à ce point. Cependant, l'opérateur "+" convertit simplement la chaîne à NaN à partir du moment où la chaîne contient le moindre caractère non valide. Vous pouvez tester ce comportement en manipulant la chaîne "10.2abc" avec chaque méthode dans la console afin de mieux comprendre les différences.

Les chaînes de caractères

Les chaînes en JavaScript sont des séquences de caractères Unicode. Cette nouvelle devrait être bien accueillie par toute personne qui a déjà eu affaire à des problèmes d'internationalisation. Pour être plus précis, ce sont des séquences de codets UTF-16 : chaque codet est représenté par un nombre sur 16 bits et chaque caractère Unicode est représenté par 1 ou 2 codets.

Si vous voulez représenter un seul caractère, il suffit d'utiliser une chaîne qui contient un seul caractère.

Pour connaître la longueur d'une chaîne, utilisez sa propriété length :

js
"bonjour".length; // 7

C'est notre première rencontre avec les objets JavaScript ! Les chaînes peuvent également être utilisées comme des objets. Elles possèdent aussi des méthodes permettant de manipuler la chaîne et d'accéder à certaines informations sur cette chaîne de caractères :

js
"bonjour".charAt(0); // "b"
"coucou monde".replace("coucou", "bonjour"); // "bonjour monde"
"bonjour".toUpperCase(); // "BONJOUR"

Les autres types

JavaScript fait la distinction entre null, qui est un objet de type object indiquant une absence délibérée de valeur, et undefined qui est un objet de type undefined indiquant une variable non initialisée — c'est-à-dire qui n'a pas encore été assignée. Nous parlerons des variables plus tard, mais en JavaScript il est possible de déclarer une variable sans lui assigner de valeur. Si vous faites cela, le type de la variable sera undefined qui est une constante.

JavaScript dispose d'un type booléen, dont les valeurs possibles sont true (vrai) et false (faux). L'un et l'autre sont des mots clés. Toute valeur peut être convertie en une valeur booléenne selon les règles suivantes :

  1. false, 0, la chaîne vide (""), NaN, null et undefined deviennent toutes false
  2. toutes les autres valeurs deviennent true.

Cette conversion peut être faite de manière explicite à l'aide de la fonction Boolean() :

js
Boolean(""); // false
Boolean(234); // true

Cependant, c'est rarement nécessaire, puisque JavaScript effectuera cette conversion silencieusement chaque fois qu'il attend une valeur booléenne, par exemple dans une instruction if (voir plus bas). Pour cette raison, on parle souvent simplement de valeurs « vraies » et « fausses » pour indiquer des valeurs devenant respectivement true et false lorsqu'elles sont converties en valeurs booléennes.

Les opérations booléennes comme && (et logique), || (ou logique) et ! (non logique) sont également gérées, comme on le verra plus bas.

Les variables

En JavaScript, on peut déclarer de nouvelles variables grâce à l'un de ces trois mots-clés : let, const, ou var.

let permet de déclarer des variables qui pourront être utilisées dans un bloc. La variable déclarée avec let est uniquement disponible dans le bloc qui contient la déclaration.

js
let a;
let nom = "Simon";

Voici un exemple de portée avec let :

js
// variableLet n'est pas utilisable ici

for (let variableLet = 0; variableLet < 5; variableLet++) {
  // variableLet peut être utilisée ici
}

// variableLet n'est pas utilisable ici

const permet de déclarer des variables dont la valeur ne doit pas changer. Une variable déclarée avec const est disponible dans le bloc dans lequel elle est déclarée.

js
const Pi = 3.14; // la constante Pi est définie
Pi = 1; // produira une erreur, car on ne peut pas modifier une variable constante.

var est le mot-clé le plus fréquemment utilisé pour déclarer des variables. Ce mot-clé était disponible avant let et const (c'était alors le seul qui permettait de déclarer des variables). Une variable qu'on déclare avec var est disponible dans la fonction dans laquelle elle est déclarée.

js
var a;
var nom = "simon";

Voici un exemple pour étudier la portée d'une variable déclarée avec var :

js
// variableVar *est* utilisable ici

for (var variableVar = 0; variableVar < 5; variableVar++) {
  // variableVar *est* également disponible ici
}

// variableVar *est* toujours disponible ici

Si on déclare une variable sans lui affecter aucune valeur, son type sera alors undefined.

JavaScript possède une différence importante quant aux autres langages de programmation comme Java : en JavaScript, les blocs ne créent pas de portées pour les variables déclarées avec var, c'est la fonction qui gère la portée d'une variable déclarée avec var. Aussi, si une variable est définie avec var au sein d'une instruction conditionnelle avec if, cette variable sera visible depuis l'ensemble de la fonction. Avec ECMAScript 2015, les instructions de déclarations, let et const permettent de créer des variables dont la portée est limitée à celle du bloc qui l'englobe.

Les opérateurs

Les opérateurs numériques en JavaScript sont +, -, *, / et % (qui est l'opérateur de reste, à ne pas confondre avec le « modulo » mathématique). Les valeurs sont affectées à l'aide de = et il existe également des opérateurs d'affectation combinés comme += et -=. Ils sont équivalents à x = x opérateur y.

js
x += 5;
x = x + 5;

Vous pouvez utiliser ++ et -- respectivement pour incrémenter et pour décrémenter. Ils peuvent être utilisés comme opérateurs préfixes ou suffixes.

L'opérateur + permet également de concaténer des chaînes :

js
"coucou" + " monde"; // "coucou monde"

Si vous additionnez une chaîne à un nombre (ou une autre valeur), tout est d'abord converti en une chaîne. Ceci pourrait vous surprendre :

js
"3" + 4 + 5; // "345"
3 + 4 + "5"; // "75"

L'ajout d'une chaîne vide à une valeur est une manière utile de convertir cette valeur une chaîne de caractères.

Les comparaisons en JavaScript se font à l'aide des opérateurs <, >, <= et >=. Ceux-ci fonctionnent tant pour les chaînes que pour les nombres. L'égalité est un peu moins évidente. L'opérateur double égal effectue une équivalence si vous lui donnez des types différents, ce qui donne parfois des résultats intéressants :

js
123 == "123"; // true
1 == true; // true

Pour éviter les conversions implicites avant les comparaisons, utilisez l'opérateur triple égal :

js
123 === "123"; //false
true === true; // true

Les opérateurs != et !== existent également.

JavaScript dispose également d'opérations bit à bit.

Les structures de contrôle

JavaScript dispose d'un ensemble de structures de contrôle similaires aux autres langages de la famille du langage C. Les structures conditionnelles sont présentes avec if et else ; lesquels peuvent être chaînés si nécessaire :

js
let nom = "des chatons";
if (nom == "des chiots") {
  nom += " !";
} else if (nom == "des chatons") {
  nom += " !!";
} else {
  nom = " !" + nom;
}
nom == "des chatons !!";

JavaScript dispose également de boucles while et do-while. Les premières permettent de former des boucles basiques ; les secondes permettent de construire des boucles qui seront exécutées au moins une fois :

js
while (true) {
  // une boucle infinie !
}

let input;
do {
  input = getInput();
} while (inputNonValide(input));

Les boucles for en JavaScript sont les mêmes qu'en C et en Java : elles permettent de fournir les informations de contrôle de la boucle en une seule ligne.