Introduction de JavaScript

JavaScript est un langage de programmation dynamique et interprété principalement utilisé pour apporter des interactions et de l'interactivité aux pages web. Développé à l'origine par Netscape dans les années 1990, il est devenu l'un des trois langages fondamentaux du développement web, aux côtés de HTML et CSS. Contrairement à ces derniers, JavaScript permet de manipuler le contenu d'une page web en temps réel sans nécessiter de rechargement de page, grâce à ce qu'on appelle le "DOM" (Document Object Model), la structure hiérarchique d'une page HTML.

Caractéristiques de JavaScript :

  • Langage interprété : JavaScript est exécuté par le navigateur sans besoin de compilation, ce qui le rend rapide et réactif pour les modifications en temps réel.
  • Basé sur les événements : JavaScript peut réagir aux actions de l'utilisateur (clics, survols, saisies de texte, etc.), offrant ainsi des fonctionnalités interactives sur le web.
  • Orientation objet et fonctionnelle : JavaScript prend en charge des paradigmes de programmation orientée objet, fonctionnelle et événementielle, ce qui le rend polyvalent et adaptable à de nombreux besoins.
  • Portabilité : JavaScript est supporté par tous les navigateurs modernes et fonctionne sur presque toutes les plateformes, ce qui en fait un choix universel pour le développement web.

Applications principales de JavaScript :

  • Manipulation du DOM : Permet de créer, modifier, et supprimer des éléments HTML en temps réel, comme changer le contenu d'une page, afficher des messages d'erreur, ou mettre à jour des données affichées.
  • Validation des formulaires : JavaScript est couramment utilisé pour valider les données saisies par l'utilisateur avant leur envoi au serveur, offrant ainsi une première couche de sécurité.
  • Effets et animations : Avec les bibliothèques comme jQuery et les frameworks modernes, JavaScript rend possible l'animation de pages, comme les menus déroulants, les carrousels d'images et les transitions.
  • Appels asynchrones (AJAX) : Grâce à AJAX (Asynchronous JavaScript and XML), JavaScript peut communiquer avec un serveur en arrière-plan, ce qui permet de mettre à jour des parties de la page sans la recharger intégralement, offrant ainsi une expérience utilisateur fluide.
  • Programmation côté serveur : Avec des environnements comme Node.js, JavaScript peut être utilisé pour le développement backend, rendant possible la création d'applications complètes uniquement en JavaScript.

Importance de JavaScript dans l'écosystème web : JavaScript est aujourd'hui incontournable dans le développement d'applications web modernes. Avec des frameworks populaires comme React, Angular et Vue, il permet de construire des interfaces utilisateur dynamiques et évolutives. En backend, Node.js a ouvert la voie à des applications full-stack en JavaScript, facilitant la collaboration entre développeurs frontend et backend. Les API modernes de JavaScript, comme les API Canvas, WebGL, et WebSockets, permettent également de créer des jeux, des visualisations de données, et des applications en temps réel.

En résumé, JavaScript est essentiel pour le développement web, car il offre des possibilités infinies pour rendre les sites interactifs, dynamiques et agréables pour l'utilisateur. La combinaison de sa puissance, de sa polyvalence et de son accessibilité fait de JavaScript un pilier central de l'expérience utilisateur sur le web.

JavaScript de Base

I. Introduction

JavaScript est un langage de programmation essentiel dans le développement web moderne. Il permet d'ajouter des fonctionnalités interactives aux sites web, comme des animations, des cartes dynamiques ou des jeux. L'un des éléments fondamentaux de ce langage est l'utilisation des variables.

Une variable est un conteneur permettant de stocker des données qui peuvent être manipulées et réutilisées tout au long de l'exécution d'un programme. Elle offre une grande flexibilité pour gérer des informations dynamiques, ce qui est crucial dans les applications web interactives.

Ce cours a pour objectif de vous familiariser avec le concept des variables en JavaScript, leurs types, leurs caractéristiques, et leurs bonnes pratiques. Vous apprendrez également à les utiliser efficacement pour créer des programmes robustes et maintenables.

  • Durée estimée : 60 minutes
  • Prérequis : Connaissances de base en HTML, CSS et notions de logique algorithmique.

Définition d'une Variable

Une variable est un élément fondamental en programmation qui permet de stocker, manipuler et référencer des données dans un programme. Dans le contexte de JavaScript, une variable est un conteneur pour une valeur qui peut être de différents types, tels que :

  • Nombre : Exemple - 42
  • Chaîne de caractères : Exemple - "Bonjour"
  • Objet : Exemple - { nom: "Alice", age: 30 }
  • Tableau : Exemple - [1, 2, 3]
  • Fonction : Exemple - function() { console.log("Hello!"); }

Une variable est définie par un identifiant (son nom) et une valeur. L'identifiant est utilisé pour accéder à la valeur stockée dans la variable et pour modifier cette valeur si nécessaire. Les variables permettent aux développeurs de gérer facilement les données dans leur programme, de les organiser et de les manipuler en fonction des besoins spécifiques de l'application.

En JavaScript, les variables peuvent être déclarées en utilisant les mots-clés suivants : var, let, et const. Chaque mot-clé possède des propriétés et des comportements spécifiques qui influencent la portée, l'assignation et la déclaration des variables.

III. Utilité des Variables

Les variables jouent un rôle central dans la programmation, et en particulier en JavaScript. Elles permettent de stocker des données, de les manipuler et de les référencer dans différentes parties d'un programme. Voici pourquoi elles sont indispensables :

A. Stockage de données

Les variables permettent de conserver des informations en mémoire pour les utiliser ultérieurement. Par exemple, elles peuvent contenir :

  • Le nom d'un utilisateur (let nomUtilisateur = "Alice";)
  • Un score dans un jeu (let score = 100;)
  • Une configuration système (const config = { theme: "clair" };)

B. Réutilisation et flexibilité

Une variable permet d'éviter la duplication de valeurs dans le code. Ainsi, si une donnée change, il suffit de la mettre à jour dans une seule variable, et toutes les parties du programme utilisant cette variable seront automatiquement mises à jour.

Exemple :

let tauxTva = 0.2;
let prix = 100;
let prixAvecTva = prix * (1 + tauxTva); // Calcul automatique
console.log(prixAvecTva); // Affiche : 120

C. Calculs et opérations logiques

Les variables facilitent les opérations complexes, qu'elles soient mathématiques ou logiques. Elles permettent de stocker les résultats intermédiaires ou d'agir comme des compteurs dans des boucles.

Exemple :

let compteur = 0;
for (let i = 0; i < 10; i++) {
    compteur += i;
}
console.log(compteur); // Affiche : 45

D. Organisation et structuration du code

Les variables permettent de structurer le code en regroupant les informations connexes. Cela rend le programme plus lisible et plus facile à maintenir.

Exemple :

const utilisateur = {
    nom: "Alice",
    age: 30,
    email: "alice@example.com"
};
console.log(utilisateur.nom); // Affiche : Alice

E. Adaptabilité

Les variables rendent les programmes dynamiques et adaptables. Par exemple, elles permettent de changer la langue d'une application ou d'ajuster le design en fonction des préférences utilisateur sans modifier le code en profondeur.

IV. Types de Variables

En JavaScript, les variables peuvent être déclarées à l'aide de trois mots-clés principaux : var, let, et const. Chacun de ces mots-clés présente des caractéristiques spécifiques influençant leur portée, leur réassignation, et leur comportement global.

A. var : Le mot-clé historique

Caractéristiques :

  • Portée fonctionnelle ou globale : Une variable déclarée avec var est accessible dans toute la fonction ou dans tout le script si elle est déclarée en dehors d'une fonction.
  • Hoisting : Les variables var sont "élevées" au sommet de leur portée, mais non initialisées.

Exemple :

function testVar() {
    if (true) {
        var message = "Accessible partout dans la fonction";
    }
    console.log(message); // Affiche : Accessible partout dans la fonction
}
testVar();

B. let : Pour des variables modernes

Caractéristiques :

  • Portée de bloc : Une variable déclarée avec let est accessible uniquement dans le bloc où elle est définie.
  • Réassignation : Une variable let peut être réassignée après sa déclaration initiale.

Exemple :

if (true) {
    let compteur = 0;
    compteur += 1;
    console.log(compteur); // Affiche : 1
}
console.log(compteur); // Erreur : compteur n'est pas défini en dehors du bloc

C. const : Pour des constantes

Caractéristiques :

  • Immuable : Une fois initialisée, une variable const ne peut plus être réassignée.
  • Portée de bloc : Similaire à let, const est limité au bloc où il est défini.

Exemple :

const pi = 3.14159;
pi = 3; // Erreur : réassignation d'une constante

D. Tableau récapitulatif

Mot-clé Portée Réassignation Initialisation obligatoire
var Fonction ou globale Oui Non
let Bloc Oui Non
const Bloc Non Oui

V. Déclaration des Variables

En JavaScript, les variables peuvent être déclarées à l'aide de trois mots-clés principaux : var, let, et const. Chaque mot-clé offre des caractéristiques uniques adaptées à différents scénarios de programmation. Comprendre comment et quand les utiliser est essentiel pour écrire un code clair, maintenable et performant.

A. Déclaration avec var

Le mot-clé var était la seule option disponible dans les anciennes versions de JavaScript. Cependant, son utilisation est aujourd'hui déconseillée en raison de ses limitations, notamment sa portée fonctionnelle et son comportement imprévisible avec le hoisting.

Exemple :

function ancienneDeclaration() {
    var age = 25;
    if (true) {
        var age = 30; // Redéclare et remplace la variable
    }
    console.log(age); // Affiche : 30
}
ancienneDeclaration();

B. Déclaration avec let

Le mot-clé let a été introduit avec ECMAScript 6 (ES6) pour résoudre les problèmes associés à var. Il offre une portée de bloc et permet la réassignation de la variable tout en améliorant la lisibilité et la sécurité du code.

Exemple :

if (true) {
    let compteur = 1;
    compteur += 1;
    console.log(compteur); // Affiche : 2
}
console.log(compteur); // Erreur : compteur n'est pas défini en dehors du bloc

C. Déclaration avec const

Le mot-clé const est utilisé pour déclarer des variables immuables, c'est-à-dire dont la valeur ne peut pas être réassignée après sa déclaration initiale. Il garantit également une portée de bloc.

Exemple :

const pi = 3.14;
pi = 3.14159; // Erreur : réassignation d'une constante

D. Bonnes pratiques pour la déclaration

  • Utilisez const par défaut pour déclarer vos variables, sauf si vous savez qu'elles devront être modifiées.
  • Préférez let lorsque la valeur de la variable doit être réassignée.
  • Évitez d'utiliser var, sauf pour maintenir un code existant.
  • Donnez des noms clairs et significatifs à vos variables pour améliorer la lisibilité.

E. Tableau récapitulatif

Mot-clé Portée Réassignation Initialisation obligatoire
var Fonction ou globale Oui Non
let Bloc Oui Non
const Bloc Non Oui

VI. Comparaison entre var, let, et const

Les trois mots-clés var, let, et const permettent de déclarer des variables en JavaScript. Cependant, ils ont des caractéristiques distinctes qui influencent leur portée, leur comportement et leur utilisation.

Analyse des différences

Mot-clé Portée Hoisting Réassignation Initialisation obligatoire
var Fonction ou globale Déclarée mais non initialisée (undefined) Oui Non
let Bloc Non Oui Non
const Bloc Non Non Oui

Points clés à retenir

  • var est désormais obsolète pour les nouvelles applications. Préférez let ou const.
  • Utilisez let pour des variables dont la valeur peut changer au fil du temps.
  • Utilisez const pour des valeurs constantes ou immuables.

Exemples pratiques

// Exemple avec var
var compteur = 1;
if (true) {
    var compteur = 2;
    console.log(compteur); // Affiche : 2
}
console.log(compteur); // Affiche : 2 (portée fonctionnelle ou globale)

// Exemple avec let
let compteurBloc = 1;
if (true) {
    let compteurBloc = 2;
    console.log(compteurBloc); // Affiche : 2 (portée de bloc)
}
console.log(compteurBloc); // Affiche : 1 (variable extérieure intacte)

// Exemple avec const
const pi = 3.14159;
pi = 3.14; // Erreur : réassignation impossible

Testez vos connaissances

Cliquez sur le bouton ci-dessous pour évaluer vos connaissances grâce à un quiz interactif :

VII. Exercices

Testez vos connaissances sur les variables en JavaScript en réalisant ces exercices pratiques. Ces activités couvrent les concepts fondamentaux tels que les portées, les déclarations et les bonnes pratiques.

Exercice 1 : Calcul d'aire

Déclarez deux variables, base et hauteur, pour représenter les dimensions d'un triangle. Calculez son aire en utilisant la formule (base * hauteur) / 2 et affichez le résultat dans la console.

let base = 7;
let hauteur = 4;
const aire = (base * hauteur) / 2;
console.log(`L'aire est de : ${aire} unités.`);

Exercice 2 : Portée des variables

Analysez le code suivant. Quelle sera la sortie dans la console ? Expliquez pourquoi.

function testLet() {
    let x = 10;
    if (true) {
        let x = 20;
        console.log(x); // Que va-t-il afficher ici ?
    }
    console.log(x); // Et ici ?
}
testLet();

Exercice 3 : Bonnes pratiques

Identifiez et corrigez les erreurs dans le code ci-dessous. Appliquez les bonnes pratiques pour une meilleure lisibilité et un comportement correct.

var Nom = "Alice";
var age = 30;
var adresse = 123; // Mauvaise déclaration
var email = "alice@example.com";
console.log(nomUtilisateur); // Erreur de variable

VIII. Bonnes pratiques pour les variables en JavaScript

L'utilisation correcte des variables est essentielle pour écrire un code JavaScript clair, maintenable et performant. Suivre des bonnes pratiques peut prévenir des erreurs fréquentes et améliorer la lisibilité du code.

A. Préférez const et let à var

Les variables déclarées avec var peuvent entraîner des comportements imprévus en raison de leur portée fonctionnelle et de leur hoisting. Préférez const pour les constantes et let pour les variables susceptibles d'être réassignées.

// Mauvaise pratique avec var
var compteur = 0;
for (var i = 0; i < 5; i++) {
    compteur += i;
}
console.log(i); // i est accessible ici, même hors du bloc for

// Bonne pratique avec let
let compteur = 0;
for (let i = 0; i < 5; i++) {
    compteur += i;
}
console.log("i est hors portée ici"); // Erreur

B. Donnez des noms significatifs

Les noms de variables doivent refléter leur utilité. Évitez les noms génériques comme data ou x. Préférez des noms descriptifs qui indiquent leur rôle dans le programme.

// Mauvaise pratique
let x = 100;
let y = 200;
console.log(x + y);

// Bonne pratique
const prixProduitA = 100;
const prixProduitB = 200;
console.log(prixProduitA + prixProduitB);

C. Initialisez vos variables

Toujours initialiser vos variables lors de leur déclaration permet d'éviter des comportements imprévisibles liés à des valeurs undefined.

// Mauvaise pratique
let compteur;
console.log(compteur); // Affiche undefined

// Bonne pratique
let compteur = 0;
console.log(compteur); // Affiche 0

D. Limitez l'utilisation des variables globales

Les variables globales peuvent être modifiées accidentellement par d'autres parties du code, ce qui peut entraîner des bugs difficiles à détecter. Préférez les déclarations dans des portées locales ou des blocs.

E. Utilisez des constantes pour les valeurs fixes

Les constantes, définies avec const, garantissent que les valeurs ne peuvent pas être réassignées. Cela améliore la clarté du code et évite les modifications accidentelles.

// Bonne pratique
const TAUX_TVA = 0.2;
let prixHT = 100;
let prixTTC = prixHT * (1 + TAUX_TVA);
console.log(prixTTC);

Testez vos connaissances

Mettez en pratique ces bonnes pratiques en corrigeant le code suivant :

var x = "Prix du produit";
var y = 12;
var z = y * 1.2;
console.log(x, z);

Type de données

I. Contexte

JavaScript est l'un des langages de programmation les plus populaires pour le développement web. Il permet de créer des pages interactives et dynamiques en manipulant les éléments d'une page HTML. Comprendre les types de données en JavaScript est essentiel pour écrire un code efficace et éviter les erreurs liées à une mauvaise gestion des valeurs.

En JavaScript, chaque donnée a un type. Ces types sont divisés en deux grandes catégories :

  • Types primitifs : Représentent des valeurs simples et immuables.
  • Types complexes : Représentent des structures de données plus complexes comme les objets et les tableaux.

Ce cours aborde les différents types de données disponibles en JavaScript, leurs spécificités, et les bonnes pratiques pour les utiliser efficacement.

II. Types numériques

En JavaScript, les types numériques sont utilisés pour représenter les nombres. Ils permettent de manipuler les valeurs numériques pour des calculs, des comparaisons ou encore des algorithmes complexes. Les principaux types numériques sont :

  • A. Le type Number : Pour les entiers et les nombres à virgule flottante.
  • B. Le type BigInt : Pour des valeurs numériques très grandes ou très précises.
  • C. Le NaN : Une valeur spéciale qui signifie "Not-a-Number".

A. Le type Number

Le type Number est utilisé pour représenter les nombres, qu'ils soient entiers ou à virgule flottante. Il s'agit du type numérique principal en JavaScript.

Exemples :

// Nombre entier
let entier = 42;

// Nombre à virgule flottante
let decimal = 3.14;

// Opérations mathématiques
let somme = entier + decimal;
console.log(somme); // Affiche : 45.14

B. Le type BigInt

Le type BigInt est utilisé pour représenter des entiers extrêmement grands ou très précis qui dépassent les limites du type Number. Il est particulièrement utile pour des calculs financiers ou scientifiques nécessitant une grande précision.

Exemple :

// Nombre entier normal
let grandNombre = 12345678901234567890n;

// Opérations avec BigInt
let double = grandNombre * 2n;
console.log(double); // Affiche : 24691357802469135780n

C. Le NaN

NaN, qui signifie "Not-a-Number", est une valeur spéciale qui apparaît lorsque vous effectuez une opération mathématique invalide. Bien que NaN soit un type Number, il indique une erreur numérique.

Exemple :

// Division par une chaîne de caractères
let resultat = 42 / "abc";
console.log(resultat); // Affiche : NaN

// Vérification de NaN
console.log(isNaN(resultat)); // Affiche : true

Exercices : Types numériques

Testez vos connaissances sur les types numériques en JavaScript en répondant aux questions suivantes :

Exercice 1 : Manipulation des nombres

Déclarez deux variables pour des nombres, effectuez une opération de multiplication, puis affichez le résultat dans la console.

// Exemple attendu
let a = 6;
let b = 7;
let resultat = a * b;
console.log(`Le résultat est : ${resultat}`);

Exercice 2 : Utilisation de BigInt

Déclarez une variable grandNombre avec une valeur supérieure à 9007199254740991 (limite du type Number) en utilisant BigInt. Doublez cette valeur et affichez-la dans la console.

// Exemple attendu
let grandNombre = 12345678901234567890n;
let double = grandNombre * 2n;
console.log(double);

Exercice 3 : Vérification de NaN

Essayez de diviser un nombre par une chaîne de caractères, puis vérifiez si le résultat est NaN en utilisant isNaN.

// Exemple attendu
let resultat = 42 / "abc";
console.log(isNaN(resultat)); // Affiche true

III. Les autres types primitifs

En JavaScript, plusieurs autres types primitifs existent pour représenter des données spécifiques. Ces types incluent :

A. Le type Boolean

Le type Boolean ne peut prendre que deux valeurs : true (vrai) ou false (faux). Il est souvent utilisé pour les conditions ou les vérifications logiques.

Exemple :

// Exemple de type Boolean
let estConnecte = true;
let aDuCredit = false;

// Utilisation dans une condition
if (estConnecte) {
    console.log("Bienvenue, utilisateur !");
} else {
    console.log("Veuillez vous connecter.");
}

B. Le type String

Le type String est utilisé pour manipuler des textes ou des séquences de caractères. Les chaînes de caractères peuvent être entourées de guillemets simples, doubles ou backticks.

Exemple :

// Chaînes de caractères
let nom = "Alice";
let message = `Bienvenue, ${nom} !`;

// Affichage du message
console.log(message); // Affiche : Bienvenue, Alice !

C. Le type Symbol

Le type Symbol permet de créer des identifiants uniques. Ces identifiants sont souvent utilisés comme clés pour des objets ou dans des cas spécifiques.

Exemple :

// Création d'un symbole unique
let id = Symbol("id");

// Utilisation dans un objet
let utilisateur = {
    [id]: 12345,
    nom: "Alice"
};

console.log(utilisateur[id]); // Affiche : 12345

D. Le type Null

Null représente une absence intentionnelle de valeur. Il est utilisé pour indiquer qu'une variable ne contient aucune donnée.

Exemple :

// Déclaration avec null
let resultat = null;
console.log(resultat); // Affiche : null

E. Le type Undefined

Undefined signifie qu'une variable a été déclarée, mais qu'aucune valeur ne lui a encore été assignée.

Exemple :

// Variable non initialisée
let x;
console.log(x); // Affiche : undefined

Exercices : Les autres types primitifs

Testez vos connaissances sur les types primitifs en JavaScript à travers ces exercices :

Exercice 1 : Le type Boolean

Déclarez une variable estConnecte initialisée à true. Ajoutez une condition pour afficher "Bienvenue" si elle est vraie, ou "Veuillez vous connecter" si elle est fausse.

// Exemple attendu
let estConnecte = true;

// Condition
if (estConnecte) {
    console.log("Bienvenue");
} else {
    console.log("Veuillez vous connecter");
}

Exercice 2 : Le type String

Déclarez une variable nom avec la valeur "Alice". Utilisez les backticks pour créer une chaîne affichant "Bienvenue, Alice !" dans la console.

// Exemple attendu
let nom = "Alice";
console.log(`Bienvenue, ${nom} !`);

Exercice 3 : Le type Null

Déclarez une variable resultat initialisée à null, puis attribuez-lui une nouvelle valeur et affichez-la.

// Exemple attendu
let resultat = null;
resultat = 42;
console.log(resultat); // Affiche : 42

Exercice 4 : Le type Symbol

Créez un symbole unique appelé id avec la description "identifiant". Utilisez ce symbole comme clé dans un objet utilisateur et affichez la valeur associée au symbole.

// Exemple attendu
let id = Symbol("identifiant");
let utilisateur = {
    [id]: 12345
};
console.log(utilisateur[id]); // Affiche : 12345

Exercice 5 : Le type Undefined

Déclarez une variable x sans lui assigner de valeur, puis affichez sa valeur dans la console. Ensuite, assignez-lui une valeur et affichez à nouveau la variable.

// Exemple attendu
let x;
console.log(x); // Affiche : undefined
x = "Nouvelle valeur";
console.log(x); // Affiche : Nouvelle valeur

IV. Essentiel

Les types de données en JavaScript sont fondamentaux pour manipuler les valeurs et écrire un code efficace. Voici les points clés à retenir :

  • Types numériques :
    • Number : Représente les entiers et les nombres à virgule flottante.
    • BigInt : Manipule des nombres extrêmement grands.
    • NaN : Indique une erreur numérique ("Not-a-Number").
  • Autres types primitifs :
    • Boolean : Représente des valeurs de vérité (true ou false).
    • String : Manipule du texte, entouré de guillemets simples, doubles ou backticks.
    • Symbol : Crée des identifiants uniques.
    • Null : Indique une absence intentionnelle de valeur.
    • Undefined : Indique qu'une variable a été déclarée mais non initialisée.
  • Bonnes pratiques :
    • Utilisez les types appropriés pour chaque situation.
    • Initialisez toujours vos variables pour éviter des erreurs inattendues.
    • Manipulez les objets et les symboles avec précaution pour éviter les collisions de clés.

Ces connaissances sont cruciales pour écrire un code JavaScript robuste et maintenable. Assurez-vous de les pratiquer régulièrement pour les maîtriser.

Vidéo explicative sur les variables en JavaScript :

Auteur de la vidéo : Melvynx

🐦 Mon Twitter : @melvynxdev
🖥 Mon GitHub : https://github.com/Melvynx
📑 Mon Blog : https://codelynx.dev
Le club du développeur secret : https://codelynx.dev/club

Description de la vidéo : Cours GRATUIT sur JavaScript : https://codelynx.dev/beginjavascript/...

I. Contexte

Les opérateurs en JavaScript sont des éléments fondamentaux du langage, permettant de manipuler et de comparer des données, d'affecter des valeurs, et bien plus encore. Ils constituent des outils essentiels pour construire des expressions, effectuer des calculs et prendre des décisions dans votre code.

Ce cours aborde les principaux types d'opérateurs utilisés en JavaScript, tels que les opérateurs arithmétiques, d'affectation, de comparaison, logiques et spécifiques aux chaînes de caractères. En maîtrisant ces concepts, vous pourrez écrire des scripts plus puissants et efficaces.

Durée : Environ 60 minutes
Pré-requis : Comprendre les bases des variables et des types de données en JavaScript.

II. Les opérateurs arithmétiques et d'affectation

Les opérateurs arithmétiques et d'affectation sont utilisés pour effectuer des calculs et assigner des valeurs aux variables en JavaScript. Ils permettent de manipuler des données numériques et de gérer facilement les calculs complexes dans vos programmes.

A. Les opérateurs arithmétiques

Les opérateurs arithmétiques effectuent des calculs mathématiques sur des nombres. Voici les principaux opérateurs disponibles :

  • + : Addition
  • - : Soustraction
  • * : Multiplication
  • / : Division
  • % : Modulo (reste de la division)
  • ** : Exponentiation

Exemples :

// Addition
let somme = 5 + 3;

// Division
let resultat = 10 / 2;

// Modulo
let reste = 7 % 3;

// Exponentiation
let puissance = 2 ** 3;

console.log(somme, resultat, reste, puissance);

B. Les opérateurs d'affectation

Les opérateurs d'affectation permettent d'assigner des valeurs aux variables et de combiner des calculs en une seule opération. Voici les principaux opérateurs d'affectation :

  • = : Affectation simple
  • += : Ajoute une valeur à la variable
  • -= : Soustrait une valeur à la variable
  • *= : Multiplie la variable par une valeur
  • /= : Divise la variable par une valeur
  • %= : Affecte le reste de la division

Exemples :

// Affectation simple
let total = 10;

// Ajoute 5 au total
total += 5;

// Multiplie par 2
total *= 2;

console.log(total); // Affiche : 30

C. Opérateurs pour les chaînes de caractères

En JavaScript, l’opérateur + peut également être utilisé pour concaténer des chaînes de caractères. Il permet de combiner plusieurs chaînes en une seule.

Exemple :

// Concaténation de chaînes
let prenom = "Alice";
let nom = "Dupont";

// Résultat : Alice Dupont
let nomComplet = prenom + " " + nom;

console.log(nomComplet);

Exercices : Les opérateurs arithmétiques et d’affectation

Testez vos connaissances en résolvant les exercices suivants :

Exercice 1 : Les opérateurs arithmétiques

Déclarez deux variables a et b avec les valeurs 10 et 3. Effectuez une addition, une multiplication, un modulo, et affichez les résultats dans la console.

// Exemple attendu
let a = 10;
let b = 3;
console.log(a + b); // Affiche : 13
console.log(a * b); // Affiche : 30
console.log(a % b); // Affiche : 1

Exercice 2 : Les opérateurs d’affectation

Déclarez une variable x avec la valeur 20. Ajoutez-lui 10, puis divisez-la par 2. Affichez le résultat final dans la console.

// Exemple attendu
let x = 20;
x += 10;
x /= 2;
console.log(x); // Affiche : 15

Exercice 3 : Concaténation de chaînes

Déclarez deux variables prenom et nom avec les valeurs "Alice" et "Dupont". Concaténez-les pour afficher "Alice Dupont" dans la console.

// Exemple attendu
let prenom = "Alice";
let nom = "Dupont";
console.log(prenom + " " + nom); // Affiche : Alice Dupont

III. Les opérateurs de comparaison et logiques

Les opérateurs de comparaison et logiques sont essentiels pour évaluer des conditions et contrôler le flux d’un programme. Ils sont principalement utilisés dans des instructions conditionnelles telles que if, else, ou les boucles.

A. Les opérateurs de comparaison

Les opérateurs de comparaison permettent de comparer deux valeurs et renvoient un résultat boolean (true ou false). Voici les principaux opérateurs :

  • == : Égalité abstraite (ne vérifie pas les types).
  • === : Égalité stricte (vérifie les types).
  • != : Différence abstraite.
  • !== : Différence stricte.
  • > : Supérieur.
  • < : Inférieur.
  • >= : Supérieur ou égal.
  • <= : Inférieur ou égal.

Exemples :

// Comparaison stricte
console.log(5 === 5); // true
console.log(5 === "5"); // false

// Supérieur ou égal
console.log(10 >= 5); // true

B. Les opérateurs logiques

Les opérateurs logiques permettent de combiner plusieurs conditions et renvoient une valeur boolean. Voici les principaux opérateurs :

  • && : ET logique. Renvoie true si toutes les conditions sont vraies.
  • || : OU logique. Renvoie true si au moins une condition est vraie.
  • ! : NON logique. Inverse la valeur boolean.

Exemples :

// ET logique
let a = 5;
let b = 10;
console.log(a > 3 && b < 15); // true

// OU logique
console.log(a > 10 || b > 5); // true

// NON logique
console.log(!(5 > 10)); // true

Exercices : Les opérateurs de comparaison et logiques

Testez vos connaissances sur les opérateurs de comparaison et logiques en résolvant les exercices suivants :

Exercice 1 : Comparaison stricte

Déclarez deux variables a et b avec les valeurs 10 et "10". Comparez-les en utilisant == et ===, puis affichez les résultats dans la console.

// Exemple attendu
let a = 10;
let b = "10";

console.log(a == b); // true
console.log(a === b); // false

Exercice 2 : Opérateurs logiques

Déclarez deux variables x et y avec les valeurs 5 et 15. Utilisez les opérateurs &&, ||, et ! pour évaluer différentes conditions et affichez les résultats.

// Exemple attendu
let x = 5;
let y = 15;

console.log(x > 3 && y < 20); // true
console.log(x > 10 || y > 10); // true
console.log(!(x < 10)); // false

IV. Essentiel

Les opérateurs en JavaScript sont des outils indispensables pour manipuler des valeurs, évaluer des conditions, et construire des expressions logiques. Voici un résumé des points essentiels à retenir :

  • Opérateurs arithmétiques :
    • Effectuent des calculs mathématiques (+, -, *, /, %, **).
    • Sont souvent combinés avec des opérateurs d'affectation pour simplifier le code.
  • Opérateurs d'affectation :
    • Utilisés pour assigner des valeurs aux variables (=).
    • Permettent de combiner les calculs avec l'affectation (+=, -=, *=, /=).
  • Opérateurs de comparaison :
    • Évaluent des relations entre deux valeurs (==, ===, !=, >, <, >=, <=).
    • Renvoient toujours un résultat boolean (true ou false).
  • Opérateurs logiques :
    • Combinent plusieurs conditions (&&, ||, !).
    • Sont essentiels dans les structures conditionnelles.
  • Concaténation :
    • L’opérateur + est utilisé pour combiner des chaînes de caractères.
    • Les backticks (`) sont recommandés pour les chaînes complexes et dynamiques.

Une bonne maîtrise de ces opérateurs vous permettra d’écrire un code plus concis, performant, et facile à comprendre.

I. Contexte

Les conditions sont des blocs essentiels en programmation. Elles permettent de contrôler l'exécution du code en fonction de certaines situations ou valeurs. En JavaScript, les conditions permettent de prendre des décisions dynamiques et d'exécuter des instructions spécifiques en fonction des besoins du programme.

Ce cours couvre les principales instructions conditionnelles telles que if, else, et switch, ainsi que des opérateurs conditionnels avancés comme l’opérateur ternaire (?) et l’opérateur nullish (??).

Durée : Environ 45 minutes
Pré-requis : Comprendre les bases des variables, types de données, et opérateurs en JavaScript.

II. Les instructions conditionnelles

Les instructions conditionnelles permettent de prendre des décisions dans un programme, en exécutant certains blocs de code en fonction des conditions spécifiées. JavaScript offre plusieurs types d'instructions conditionnelles, dont les plus courantes sont if, else, et switch.

A. Les instructions if et else

L'instruction if permet d'exécuter un bloc de code uniquement si une condition est vraie. Si la condition est fausse, vous pouvez utiliser l'instruction else pour exécuter un autre bloc de code.

Syntaxe de base :


if (condition) {
    // Code à exécuter si la condition est vraie
} else {
    // Code à exécuter si la condition est fausse
}

Vous pouvez également utiliser else if pour tester plusieurs conditions.

Syntaxe avec else if :


if (condition1) {
    // Code si condition1 est vraie
} else if (condition2) {
    // Code si condition2 est vraie
} else {
    // Code si aucune condition n'est vraie
}

Exemple :

// Déclaration d'une variable
let age = 18;

// Vérification de l'âge
if (age >= 18) {
    console.log("Vous êtes majeur.");
} else {
    console.log("Vous êtes mineur.");
}

Dans cet exemple, si la variable age est supérieure ou égale à 18, le message "Vous êtes majeur." sera affiché, sinon "Vous êtes mineur." s'affichera.

B. L’instruction switch

L'instruction switch permet de comparer une variable ou une expression à plusieurs valeurs possibles et d'exécuter un bloc de code en fonction de la valeur qui correspond. Elle est souvent plus lisible lorsque vous devez tester plusieurs valeurs possibles.

Syntaxe de base :


switch (expression) {
    case valeur1:
        // Code à exécuter si expression === valeur1
        break;
    case valeur2:
        // Code à exécuter si expression === valeur2
        break;
    default:
        // Code à exécuter si aucune valeur ne correspond
}

L'instruction break est utilisée pour sortir du bloc switch après l'exécution du code associé à un case. Si aucune valeur ne correspond, l'instruction default est exécutée.

Exemple :

// Déclaration d'une variable
let jour = "lundi";

// Utilisation de switch pour déterminer le jour de la semaine
switch (jour) {
    case "lundi":
        console.log("Lundi, début de la semaine.");
        break;
    case "vendredi":
        console.log("Vendredi, presque le week-end.");
        break;
    default:
        console.log("C'est un autre jour.");
}

Dans cet exemple, si la variable jour est égale à "lundi", le message "Lundi, début de la semaine." sera affiché. Si la variable est égale à "vendredi", un autre message s'affichera, et si aucune des conditions n'est remplie, le message par défaut sera exécuté.

Exercices : Les instructions conditionnelles

Testez vos connaissances sur les instructions conditionnelles en résolvant ces exercices interactifs :

Exercice 1 : Utilisation de if et else

Déclarez une variable temperature et assignez-lui une valeur numérique. Utilisez une condition if pour vérifier si la température est inférieure à 0. Si c'est le cas, affichez "Il fait froid." Sinon, affichez "La température est agréable."

// Exemple attendu
let temperature = 5;

if (temperature < 0) {
    console.log("Il fait froid.");
} else {
    console.log("La température est agréable.");
}

Exercice 2 : Utilisation de switch

Déclarez une variable jour avec une valeur correspondant à un jour de la semaine (par exemple "lundi"). Utilisez une instruction switch pour afficher un message différent selon le jour.

// Exemple attendu
let jour = "lundi";

switch (jour) {
    case "lundi":
        console.log("Début de la semaine.");
        break;
    case "vendredi":
        console.log("Presque le week-end.");
        break;
    default:
        console.log("Un jour comme les autres.");
}

III. Les opérateurs conditionnels

En JavaScript, les opérateurs conditionnels permettent d’évaluer des expressions et de retourner des valeurs selon certaines conditions. Ils sont utilisés pour simplifier les instructions conditionnelles.

A. L’opérateur ternaire

L'opérateur ternaire (condition ? valeur_si_vrai : valeur_si_faux) est une forme concise de la structure conditionnelle if-else. Il permet d'évaluer une condition et de retourner une des deux valeurs possibles.

Syntaxe :


condition ? valeur_si_vrai : valeur_si_faux;

Cet opérateur est utile pour rendre le code plus compact, notamment lorsque la logique est simple et directe.

Exemple :

// Déclaration d'une variable
let age = 18;

// Utilisation de l'opérateur ternaire
let statut = (age >= 18) 
    ? "Majeur" 
    : "Mineur";

console.log(statut); // Affiche : "Majeur"

Dans cet exemple, si age est supérieur ou égal à 18, la variable statut prendra la valeur "Majeur". Sinon, elle prendra la valeur "Mineur".

B. L’opérateur nullish (??)

L'opérateur nullish (??) retourne la première valeur qui n'est ni null ni undefined. Il est souvent utilisé pour fournir une valeur par défaut à une variable.

Syntaxe :


valeur1 ?? valeur2

Si valeur1 est null ou undefined, l'opérateur retournera valeur2. Sinon, il retournera valeur1.

Exemple :

// Déclaration d'une variable
let username = null;

// Utilisation de l'opérateur nullish
let displayName = username ?? "Utilisateur inconnu";

console.log(displayName); // Affiche : "Utilisateur inconnu"

Dans cet exemple, comme la variable username est null, la variable displayName prendra la valeur "Utilisateur inconnu".

Exercices : Les opérateurs conditionnels

Testez vos connaissances sur les opérateurs conditionnels en résolvant ces exercices interactifs :

Exercice 1 : L’opérateur ternaire

Déclarez une variable age avec une valeur numérique. Utilisez un opérateur ternaire pour afficher "Majeur" si l’âge est supérieur ou égal à 18, et "Mineur" sinon.

// Exemple attendu
let age = 17;
let statut = (age >= 18) 
    ? "Majeur" 
    : "Mineur";

console.log(statut); // Affiche : "Mineur"

Exercice 2 : L’opérateur nullish

Déclarez une variable username avec une valeur null. Utilisez l’opérateur nullish pour assigner "Invité" si username est null ou undefined.

// Exemple attendu
let username = null;
let displayName = username ?? "Invité";

console.log(displayName); // Affiche : "Invité"

Exercice 3 : Chaînage optionnel

Déclarez un objet user sans la propriété email. Utilisez le chaînage optionnel pour accéder à user.email sans générer d’erreur, et affichez "Non disponible" si la propriété est absente.

// Exemple attendu
let user = { name: "Alice" };
let email = user?.email ?? "Non disponible";

console.log(email); // Affiche : "Non disponible"

IV. Essentiel

Les conditions en JavaScript sont indispensables pour contrôler l’exécution du code en fonction de différentes situations. Voici les points essentiels à retenir :

  • Les instructions conditionnelles :
    • if / else : Utilisées pour exécuter un bloc de code si une condition est vraie. L'instruction else permet de gérer les cas où la condition est fausse.
    • else if : Permet de tester plusieurs conditions successives.
    • switch : Pratique pour comparer une variable à plusieurs valeurs fixes, avec une option par défaut.
  • Les opérateurs conditionnels :
    • Ternaire (condition ? valeur_si_vrai : valeur_si_faux) : Simplifie les conditions courtes.
    • Nullish (??) : Fournit une valeur par défaut pour les variables null ou undefined.
    • Chaînage optionnel (?.) : Vérifie l'existence d'une propriété sans lever d'erreur si elle est absente.
    • Opérateurs logiques (&&, ||) : Permettent de combiner des conditions ou de fournir des valeurs par défaut.

Une maîtrise des conditions vous permet d’écrire des programmes dynamiques, logiques et réactifs. N'hésitez pas à combiner les différentes instructions et opérateurs pour répondre aux besoins de vos projets.

Boucles

Contexte

Pourquoi apprendre les boucles ? Les boucles sont l'un des fondements de la programmation. Elles permettent de répéter des blocs de code en fonction d'une condition donnée, automatisant ainsi des tâches complexes ou répétitives. Que ce soit pour parcourir une liste, générer des données, ou effectuer des calculs, elles sont omniprésentes en JavaScript.

Les types de boucles : En JavaScript, il existe plusieurs types de boucles :

  • La boucle for : Idéale pour parcourir une séquence avec un nombre de répétitions connu.
  • La boucle while : Utile lorsque le nombre d'itérations dépend d'une condition dynamique.
  • La boucle do/while : Similaire à while, mais garantit l'exécution au moins une fois.
  • Les boucles spéciales :
    • for/in pour parcourir les propriétés d'un objet.
    • for/of pour itérer sur les valeurs d'une collection.

Attention : Les boucles peuvent facilement mener à des erreurs comme des boucles infinies si la condition d'arrêt est mal définie. Une compréhension solide de leur fonctionnement est donc cruciale.

Applications des boucles :

  • Parcourir des tableaux ou objets.
  • Générer des séries de nombres.
  • Automatiser des tâches répétitives.

Saviez-vous ? Les boucles en JavaScript sont similaires à celles de nombreux autres langages comme Python, Java, et PHP. Une fois maîtrisées, elles faciliteront l'apprentissage d'autres langages !

La boucle for

La boucle for est utilisée lorsque le nombre d'itérations est connu à l'avance. Elle permet de parcourir des tableaux, de générer des séries ou d'exécuter des instructions répétitives.

Console log

Le moyen le plus simple de visualiser les itérations d'une boucle est d'utiliser la méthode console.log(). Cela permet de vérifier le déroulement des itérations.

Exemple :


// Affiche les nombres de 1 à 5 dans la console
for (let i = 1; i <= 5; i++) {
    console.log(i);
}

Ce code commence à i = 1 et incrémente i jusqu'à ce que la condition i <= 5 soit fausse. Chaque valeur de i est affichée dans la console.

Première utilisation de la boucle for

La boucle for est une structure essentielle en programmation. Elle est particulièrement utile lorsque le nombre d'itérations est déterminé avant l'exécution. Cela signifie que le programme connaît à l'avance combien de fois la boucle doit être répétée.

Structure de base :


for (/*initialisation*/; /*condition*/; /*incrémentation*/) {
    // Instructions à exécuter
}

Voici les éléments clés de la boucle for :

  • Initialisation : Une variable est créée pour suivre les itérations (par exemple, let i = 0).
  • Condition : Définit jusqu'à quand la boucle doit s'exécuter (par exemple, i <= 10).
  • Incrémentation : Met à jour la variable d'itération à chaque cycle (par exemple, i++).

Exemple simple

Voici un exemple simple où la boucle affiche les nombres de 1 à 10 dans la console :


// Affiche les nombres de 1 à 10 dans la console
for (let i = 1; i <= 10; i++) {
    console.log(i);
}

La boucle commence à i = 1, puis vérifie si i <= 10. Si c'est vrai, le bloc d'instructions s'exécute et i est incrémenté. Une fois que i > 10, la boucle s'arrête.

Interaction avec les tableaux

Les tableaux permettent de stocker des éléments ordonnés. Ils sont souvent utilisés avec les boucles for. Voici un exemple de tableau simple :


// Déclaration d'un tableau
let tableau = ["valeur 1", "valeur 2"];

// Accès à un élément par son index
console.log(tableau[1]); // Affiche "valeur 2"

Exemple pratique : Table de multiplication

Voici un exemple plus complexe qui génère une table de multiplication et la stocke dans un tableau :


// Génération de la table de multiplication du nombre 10
const nombre = 10;
let table = [];

for (let i = 1; i <= 10; i++) {
    let resultat = nombre * i;
    table.push(resultat); // Ajoute le résultat au tableau
}

// Affiche le 4e élément de la table (index 3)
console.log(table[3]); // Affiche : 40

Ce script utilise une boucle for pour multiplier nombre par les valeurs de 1 à 10. Les résultats sont ajoutés dans le tableau table. Cet exemple illustre la flexibilité des boucles et des tableaux.

Utiliser for/in

La boucle for/in est utilisée pour parcourir les propriétés d’un objet. Contrairement à une boucle for classique, qui est basée sur des itérations définies, for/in itère sur chaque propriété d'un objet ou index d’un tableau.

Voici la syntaxe générale :


for (/*variable*/ in /*objet*/) {
    // Instructions
}

Les objets en JavaScript

Un objet en JavaScript est une entité qui contient des propriétés et des méthodes. Une propriété représente une caractéristique ou un attribut de l'objet, tandis qu'une méthode est une fonction associée à cet objet. Par exemple :


// Déclaration d'un objet avec des propriétés
let voiture = {
    marque: "Toyota",
    modele: "Corolla",
    annee: 2022
};

Exemple : Parcourir un objet avec for/in

Voici un exemple où nous utilisons for/in pour afficher les noms des propriétés d'un objet :


// Parcourir les propriétés d'un objet
for (let propriete in voiture) {
    console.log(propriete);
}

La console affichera :

  • "marque"
  • "modele"
  • "annee"
Ici, chaque itération de la boucle for/in renvoie le nom d'une propriété de l'objet.

Exemple : Parcourir un tableau avec for/in

Lorsque vous utilisez for/in avec un tableau, vous parcourez les indices (index) des éléments du tableau. Voici un exemple :


// Déclaration d'un tableau
let marques = ["Apple", "HP", "Acer"];

// Parcourir les indices
for (let index in marques) {
    console.log(index); // Affiche 0, 1, 2
}

Attention :

Bien que for/in puisse être utilisé pour parcourir les indices d'un tableau, ce n'est pas recommandé. Voici pourquoi :

  • Les indices ne représentent pas toujours les valeurs : La boucle renvoie les indices du tableau, et non les valeurs directement.
  • Propriétés supplémentaires : Si vous ajoutez des propriétés au tableau, elles seront également parcourues par for/in, ce qui peut provoquer des erreurs.

Exemple : Accéder aux valeurs d'un tableau

Pour accéder aux valeurs d'un tableau tout en utilisant for/in, vous pouvez utiliser les indices pour récupérer les éléments :


// Parcourir les valeurs avec for/in
for (let index in marques) {
    console.log(marques[index]);
}

Dans ce cas, la console affichera :

  • "Apple"
  • "HP"
  • "Acer"
Toutefois, il est préférable d'utiliser for/of pour parcourir directement les valeurs d’un tableau, comme nous le verrons dans la prochaine section.

Utiliser for/of

La boucle for/of permet de parcourir les objets itérables, tels que les tableaux, et de récupérer directement leurs valeurs. Contrairement à for/in, qui parcourt les indices ou les clés, for/of est optimisée pour accéder aux éléments eux-mêmes.

Exemple simple : Parcourir un tableau

Voici un exemple où nous utilisons for/of pour afficher les valeurs d’un tableau dans la console :


// Parcourir les valeurs d'un tableau
let tableau = ["Apple", "HP", "Acer"];

for (let marque of tableau) {
    console.log(marque);
}

La console affichera :

  • "Apple"
  • "HP"
  • "Acer"
Dans cet exemple, la variable marque prend successivement la valeur de chaque élément du tableau à chaque itération.

Exemple avancé : Concaténation des valeurs

La boucle for/of peut également être utilisée pour manipuler les valeurs des éléments d’un tableau. Voici un exemple où nous concaténons les valeurs dans une chaîne de caractères :


// Concaténation des valeurs d'un tableau
let tableau = ["Apple", "HP", "Acer"];
let marques = "";

for (let marque of tableau) {
    marques += marque + ", ";
}

console.log(marques); // Affiche : "Apple, HP, Acer, "

Dans cet exemple :

  • À chaque itération, la valeur de marque est ajoutée à la chaîne de caractères marques.
  • Une virgule et un espace (", ") sont ajoutés après chaque valeur pour les séparer.
La console affiche finalement toutes les valeurs concaténées dans une seule chaîne.

Astuce :

La boucle for/of fonctionne avec tous les objets itérables, y compris :

  • Les tableaux.
  • Les chaînes de caractères (itère sur chaque caractère).
  • Les objets de type Map ou Set.

Si vous avez besoin de parcourir uniquement les valeurs d’un tableau ou d’un autre objet itérable, for/of est une méthode claire et efficace.

Exercices : Boucles for

Mettez en pratique vos connaissances sur les boucles for grâce à ces exercices interactifs. Cliquez sur "Vérifier" pour valider vos réponses et afficher les résultats dans la console !

Exercice 1 : Afficher une séquence de nombres pairs

Écrivez une boucle for qui affiche dans la console tous les nombres pairs de 2 à 20 inclus.


// Solution attendue :
for (let i = 2; i <= 20; i += 2) {
    console.log(i);
}

Exercice 2 : Générer une table de multiplication

Créez une boucle for qui génère la table de multiplication de 7 et affiche chaque résultat dans la console.


// Solution attendue :
const nombre = 7;

for (let i = 1; i <= 10; i++) {
    console.log(nombre * i);
}

Exercice 3 : Concaténation des valeurs d’un tableau

Écrivez une boucle for qui concatène toutes les valeurs d’un tableau dans une chaîne de caractères et affiche la chaîne concaténée dans la console.


// Tableau fourni :
let fruits = ["Pomme", "Banane", "Orange"];

// Solution attendue :
let resultat = "";

for (let i = 0; i < fruits.length; i++) {
    resultat += fruits[i] + ", ";
}

console.log(resultat); // Affiche : "Pomme, Banane, Orange, "

III. La boucle while

a. Introduction

La boucle while est utilisée lorsque le nombre d'itérations n'est pas connu à l'avance. Elle exécute des instructions tant qu'une condition donnée est vraie. Cela la différencie de la boucle for, où le nombre d'itérations est souvent défini dès le départ.

b. Utilisation

La syntaxe de la boucle while est simple et intuitive :


while (/* condition */) {
    // instructions
}

Exemple d'une boucle while :


// Affiche les nombres de 1 à 10
let nombre = 1;

while (nombre <= 10) {
    console.log("Le nombre est : " + nombre);
    nombre++;
}

Ici, la variable nombre commence à 1. La boucle s'exécute tant que nombre <= 10. La condition est vérifiée avant chaque itération, ce qui garantit que la boucle s'arrêtera une fois la condition non respectée.

c. Éviter les boucles infinies

Les boucles infinies se produisent lorsque la condition de la boucle ne devient jamais false. Cela peut bloquer ou faire planter le programme.


// Exemple de boucle infinie
let a = 120;

while (typeof(a) == "number" && (a >= 100 && a <= 140)) {
    console.log(a);
}

Dans cet exemple, la condition reste toujours vraie car a n'est jamais modifiée. Une version corrigée :


// Corrigé pour éviter une boucle infinie
let a = 120;

while (typeof(a) == "number" && (a >= 100 && a <= 140)) {
    console.log(a);
    a++;
}

d. Utilisation de do/while

La boucle do/while garantit qu'une itération sera exécutée au moins une fois, même si la condition est fausse dès le départ.


let cv = 100;

do {
    console.log("La voiture a " + cv + " cv");
    cv++;
} while (cv > 100 && cv <= 110);

Dans cet exemple, même si la condition est fausse dès le départ, l'itération initiale est effectuée.

e. Mots-clés break et continue

Les mots-clés break et continue permettent de contrôler l'exécution des boucles :

  • break : Interrompt l'exécution de la boucle et passe à l'instruction suivante après la boucle.
  • continue : Passe immédiatement à l'itération suivante, sautant les instructions restantes de l'itération en cours.

// Exemple avec break et continue
let a = 110;

while (a >= 100 && a <= 150) {
    console.log(a);
    a += 10;

    if (a == 130) {
        continue;
    } else if (a == 140) {
        break;
    }
}
console.log("Fini");

Dans cet exemple :

  • continue saute le reste de l'itération lorsque a == 130.
  • break arrête complètement la boucle lorsque a == 140.

Exercices : Boucle while

Testez vos connaissances sur les boucles while et do/while à travers ces exercices pratiques. Cliquez sur "Vérifier" pour valider vos réponses et afficher les résultats dans la console !

Question 1 : Afficher les multiples d'un nombre

Écrire la bonne condition pour que la boucle while affiche les multiples de nombre, inférieurs à 200.


// Solution attendue :
let nombre = 28;
let compteur = 1;

while (/* condition */) {
    console.log(nombre * compteur);
    compteur++;
}

Question 2 : Transformer en do/while

Transformer la boucle while suivante pour qu’une itération soit opérée avant que le programme contrôle la condition.


// Solution attendue :
let prix = 100;
let tabPrix = [];

do {
    tabPrix.push(prix);
    prix++;
} while (prix > 100 && prix <= 110);

console.log(tabPrix[2]);

Question 3 : Arrêter la boucle

Insérer le bon mot clé pour que, quand prix est égal à 108, la boucle s’arrête.


// Solution attendue :
let prix = 101;
let tabPrix = [];

while (prix > 100 && prix <= 110) {
    tabPrix.push(prix);
    if (prix == 108) {
        break;
    }
    prix++;
}

console.log(tabPrix[7]);

Question 4 : Ajouter une instruction

Insérer une instruction pour que la boucle ne soit pas infinie. L'objectif est d'afficher les nombres entiers de 0 (inclus) à 19 (inclus).


// Solution attendue :
let compteur = 0;
let nombres = "";

while (compteur < 20) {
    nombres += compteur + " ";
    compteur++;
}

console.log(nombres);

Question 5 : Vérifier les multiples de 2

Écrire une boucle while permettant de vérifier si les nombres entiers inférieurs à nombre sont des multiples de 2 ou non. La console devra afficher :

  • "multiple de 2" pour les multiples.
  • "pas un multiple de 2" sinon.

// Solution attendue :
let nombre = 15;
let compteur = 1;

while (compteur < nombre) {
    if (compteur % 2 == 0) {
        console.log(compteur + " : multiple de 2");
    } else {
        console.log(compteur + " : pas un multiple de 2");
    }
    compteur++;
}

IV. Essentiel

Dans ce cours, nous avons exploré les boucles en JavaScript, un outil fondamental pour éviter la répétition manuelle des instructions. Voici un résumé des points clés abordés :

  • La boucle for : utilisée lorsque le nombre d'itérations est fixé avant la première exécution. Elle utilise trois paramètres principaux :
    • Initialisation : Définition du compteur initial.
    • Condition : Détermine la fin de la boucle.
    • Incrémentation : Mise à jour du compteur.
  • Les variantes for/in et for/of :
    • for/in : Parcourt les propriétés d’un objet.
    • for/of : Parcourt les valeurs d’un objet itérable, comme un tableau.
  • La boucle while : utilisée lorsque le nombre d'itérations dépend des instructions exécutées. Elle continue tant que la condition spécifiée reste vraie.
  • La boucle do/while : garantit au moins une exécution avant la vérification de la condition.
  • Les mots-clés spéciaux :
    • break : Interrompt immédiatement l'exécution de la boucle et passe à l'instruction suivante.
    • continue : Interrompt une itération et passe directement à la suivante.
  • Attention aux boucles infinies : Ces boucles ne s'arrêtent jamais car leur condition reste toujours vraie. Elles peuvent provoquer le blocage ou l'arrêt du programme. Pour les éviter :
    • Assurez-vous que la condition devienne fausse à un moment donné.
    • Ajoutez des incrémentations ou des modifications logiques dans la boucle.

Les boucles sont des outils puissants en JavaScript, permettant de manipuler facilement des collections de données, d'automatiser des tâches répétitives, et bien plus encore. Une bonne compréhension de leurs mécanismes et de leurs variantes vous permettra de les utiliser efficacement dans vos programmes.

Fonctions

I. Contexte

Les fonctions sont des blocs de code conçus pour effectuer une tâche ou un ensemble de tâches spécifiques. En JavaScript, elles constituent un élément essentiel permettant de rendre le code modulaire, réutilisable et plus facile à comprendre. Les fonctions permettent également d’organiser les instructions en sections logiques, ce qui améliore la lisibilité et la maintenabilité du code.

Pourquoi utiliser les fonctions ?

Les fonctions offrent plusieurs avantages :

  • **Réutilisabilité** : Une fonction peut être appelée plusieurs fois dans le programme, évitant ainsi de répéter le même code.
  • **Organisation** : Elles permettent de structurer le code en blocs logiques, facilitant ainsi le débogage et la lecture.
  • **Flexibilité** : Grâce aux paramètres, une fonction peut être utilisée pour différentes entrées et produire des résultats variés.
  • **Abstraction** : Elles permettent de cacher les détails de l’implémentation, rendant le code plus propre et plus intuitif.

Fonctionnement des fonctions en JavaScript

En JavaScript, une fonction peut être définie de plusieurs façons, notamment :

  • Fonctions déclarées : Elles sont définies avec le mot-clé function et possèdent un nom. Ces fonctions sont « hoistées », ce qui signifie qu’elles peuvent être appelées avant leur définition dans le code.
  • Fonctions anonymes : Ces fonctions n'ont pas de nom et sont souvent utilisées comme valeurs dans des expressions ou des arguments.
  • Fonctions fléchées (arrow functions) : Introduites avec ES6, elles permettent une syntaxe plus concise pour définir des fonctions.

Dans les sections suivantes, nous examinerons comment définir, utiliser et optimiser les fonctions en JavaScript, ainsi que leurs particularités par rapport à d'autres éléments du langage.

II. Utilisation et définition de fonctions

Les fonctions en JavaScript jouent un rôle central pour organiser et réutiliser du code. Elles permettent de structurer des blocs logiques qui peuvent être invoqués à plusieurs reprises, avec des paramètres différents, pour éviter de répéter le même code.

A. Utilisation et définition de fonctions

Fonctions prédéfinies

En JavaScript, il existe de nombreuses fonctions prédéfinies, appelées fonctions natives, qui peuvent être utilisées à tout moment. Par exemple, la fonction eval() permet d’exécuter du code JavaScript contenu dans une chaîne de caractères.


// Exemple d'utilisation de eval()
const code = "const nombre = 15; console.log(nombre * 2);";
eval(code); // Affiche : 30

Ce code évalue et exécute le contenu de la chaîne passée en paramètre, comme si ce dernier faisait partie du script. Vous pouvez trouver une liste complète des fonctions natives sur la documentation officielle de Mozilla Developer Network (MDN).

Syntaxe de la définition de fonctions

Une fonction en JavaScript se définit avec la syntaxe suivante :


// Définition d'une fonction
function nomDeLaFonction(paramètres) {
    // Corps de la fonction
    instructions;
}

Le mot-clé function permet de définir une fonction. Les éventuels paramètres sont placés entre parenthèses, et les instructions à exécuter sont contenues dans les accolades. Pour utiliser une fonction, il est nécessaire de l'appeler.

Syntaxe de l'appel de fonctions

Pour appeler une fonction, utilisez son nom suivi de parenthèses. Vous pouvez y passer des arguments, correspondant aux paramètres définis dans la fonction :


// Appel d'une fonction
nomDeLaFonction(arguments);

Exemple : Première définition et appel d'une fonction

Voici un exemple où nous définissons une fonction pour calculer le double d’un nombre. La fonction est ensuite appelée plusieurs fois avec des valeurs différentes.


// Définition de la fonction calcDouble
let nombre = 100;

function calcDouble() {
    let double = nombre * 2;
    console.log(`Le double du nombre ${nombre} est ${double}`);
}

// Appels de la fonction
calcDouble(); // Affiche : Le double du nombre 100 est 200

// Modification de la variable
nombre = 40;
calcDouble(); // Affiche : Le double du nombre 40 est 80

Dans cet exemple, la fonction calcDouble() calcule le double de la variable nombre et affiche le résultat. Vous pouvez appeler cette fonction autant de fois que nécessaire sans réécrire son contenu.

Grâce aux fonctions, vous évitez la duplication de code et facilitez les modifications futures.

B. Exercice : Quiz

Cette section est désactivée pour le moment. Revenez plus tard pour tester vos connaissances sur la définition et l'appel des fonctions !

III. Paramètres, valeur de retour et expressions de fonctions

Les paramètres et les valeurs de retour sont des concepts fondamentaux en JavaScript pour rendre les fonctions dynamiques et réutilisables. Cette section détaille comment passer des données à une fonction, comment recevoir une valeur en retour, et comment utiliser les expressions de fonctions.

A. Paramètres et valeur de retour

Paramètres

Les paramètres permettent de transmettre des informations à une fonction. Ils sont définis dans les parenthèses lors de la déclaration de la fonction et utilisés dans le corps de celle-ci. Une fonction peut avoir un ou plusieurs paramètres.


// Définition avec paramètres
function multiplier(a, b) {
    return a * b;
}

// Appel avec des arguments
const resultat = multiplier(4, 5); // resultat vaut 20

Ici, la fonction multiplier prend deux paramètres a et b. Lorsqu’elle est appelée, elle retourne le produit des deux valeurs passées en arguments.

Valeur de retour

Une fonction peut renvoyer une valeur avec le mot-clé return. La valeur retournée peut ensuite être utilisée ou stockée dans une variable.


// Fonction avec valeur de retour
function ajouter(a, b) {
    return a + b;
}

// Utilisation de la valeur retournée
const somme = ajouter(10, 15); // somme vaut 25
console.log(somme); // Affiche : 25

Dans cet exemple, la fonction ajouter retourne la somme des deux arguments passés. La valeur retournée est ensuite utilisée pour afficher le résultat.

Exemple combiné : Paramètres et retour


// Calculer l'aire d'un rectangle
function aireRectangle(longueur, largeur) {
    return longueur * largeur;
}

// Appel de la fonction
const aire = aireRectangle(10, 5); // aire vaut 50
console.log(`L'aire est : ${aire}`); // Affiche : L'aire est : 50

Dans cet exemple, la fonction prend deux paramètres, calcule leur produit, et retourne l'aire du rectangle. Ce type d'approche rend votre code modulaire et réutilisable.

B. Exercice : Quiz

Cette section est désactivée pour le moment. Revenez plus tard pour tester vos connaissances sur les paramètres et les valeurs de retour des fonctions !

IV. Essentiel

Dans ce cours, nous avons exploré l'importance et l'utilisation des fonctions en JavaScript, un concept clé pour structurer et réutiliser du code. Voici un résumé des points essentiels à retenir :

  • **Les fonctions prédéfinies** : Ces fonctions sont disponibles nativement dans JavaScript et peuvent être appelées à tout moment. Exemple : eval().
  • **Définition des fonctions personnalisées** :
    • Utilisez le mot-clé function suivi d’un nom pour déclarer une fonction.
    • Ajoutez des paramètres entre parenthèses pour personnaliser l’exécution.
    • Incluez les instructions à exécuter dans des accolades.
  • **Réutilisation du code** :
    • Appelez une fonction autant de fois que nécessaire.
    • Les paramètres permettent de transmettre des données dynamiques à la fonction.
  • **Valeurs de retour** :
    • Utilisez return pour transmettre un résultat au reste du programme.
    • Les valeurs retournées peuvent être utilisées dans d'autres calculs ou affichées directement.
  • **Expressions de fonctions** :
    • Les fonctions peuvent être anonymes et assignées à des variables.
    • Elles peuvent être utilisées comme arguments ou valeurs de retour d’autres fonctions.

Les fonctions sont un élément fondamental de JavaScript. Une bonne compréhension de leur fonctionnement et de leurs possibilités est essentielle pour écrire un code propre, modulaire et maintenable.

V. Auto-évaluation

Cette section vous permet de tester vos connaissances sur les fonctions en JavaScript grâce à des exercices pratiques et des questions à choix multiples. Revenez plus tard pour évaluer votre compréhension des notions abordées.

A. Exercice

Complétez les exercices ci-dessous pour vérifier votre compréhension des fonctions :

  1. Créer une fonction qui prend deux paramètres et retourne leur somme. Testez votre fonction avec plusieurs paires de valeurs.
  2. Modifier une fonction prédéfinie : utilisez la fonction eval() pour évaluer une chaîne contenant un script simple.

B. Test

Répondez aux questions à choix multiples suivantes pour valider vos acquis sur les fonctions en JavaScript :

  • Question 1 : Quelle est la différence entre une fonction déclarée et une fonction anonyme ?
  • Question 2 : Que se passe-t-il si une fonction n’a pas de mot-clé return ?
  • Question 3 : Peut-on appeler une fonction déclarée avant sa définition dans le code ? Pourquoi ?

Manipulation du DOM et Événements

La manipulation du DOM (Document Object Model) et la gestion des événements sont des concepts essentiels pour ajouter de l'interactivité et du dynamisme à vos pages web. Ces compétences permettent de modifier les éléments HTML et CSS en temps réel, en réponse aux actions des utilisateurs.

Dans cette section, vous apprendrez à explorer et manipuler efficacement le DOM, à gérer les événements utilisateurs, et à appliquer des techniques avancées pour créer des interfaces réactives et performantes.

Sommaire

Introduction au DOM

Le DOM (Document Object Model) est une représentation en mémoire de la structure d'un document HTML ou XML. Il s'agit d'une API (Application Programming Interface) qui permet d'accéder, de manipuler et de mettre à jour dynamiquement les éléments d'une page web.

Chaque élément HTML est représenté comme un objet dans le DOM, et ces objets sont organisés en une arborescence. Le DOM agit comme une interface entre le navigateur et votre code JavaScript.

Exemple :

<!DOCTYPE html>
<html>
    <head>
        <title>Page Exemple</title>
    </head>
    <body>
        <h1>Bienvenue</h1>
        <p>Ce texte est contenu dans le DOM.</p>
    </body>
</html>
        

Vous pouvez interagir avec cette structure en JavaScript pour créer, modifier ou supprimer des éléments, ou pour réagir aux interactions des utilisateurs.

Sélection du DOM

Sélection des éléments DOM

La sélection d'éléments dans le DOM est une étape essentielle pour manipuler et interagir avec les pages web dynamiquement. JavaScript offre une variété de méthodes pour cibler des éléments spécifiques dans le document.

Les principales méthodes de sélection sont :

  • document.getElementById : Sélectionne un élément par son identifiant unique.
  • document.getElementsByClassName : Sélectionne tous les éléments ayant une classe spécifique.
  • document.getElementsByTagName : Sélectionne tous les éléments ayant un nom de balise donné.
  • document.querySelector : Sélectionne le premier élément correspondant à un sélecteur CSS.
  • document.querySelectorAll : Sélectionne tous les éléments correspondant à un sélecteur CSS.

Exemple de sélection avec différents sélecteurs


    // Sélection par ID
    const titre = document.getElementById('titre-principal');

    // Sélection par classe
    const elements = document.getElementsByClassName('classe-exemple');

    // Sélection par nom de balise
    const paragraphs = document.getElementsByTagName('p');

    // Sélection avec querySelector
    const premierParagraphe = document.querySelector('p');

    // Sélection de tous les éléments correspondants
    const tousLesParagraphes = document.querySelectorAll('p');

    // Exemple d'itération sur une NodeList
    tousLesParagraphes.forEach(paragraphe => {
        console.log(paragraphe.textContent);
    });
            

Exemple visuel

Considérez le code HTML suivant :


    <div id="conteneur">
        <h1 id="titre-principal">Bienvenue</h1>
        <p class="classe-exemple">Premier paragraphe</p>
        <p class="classe-exemple">Deuxième paragraphe</p>
    </div>
            

Voici comment sélectionner et manipuler ces éléments en JavaScript :


    // Sélection de l'élément avec l'ID 'titre-principal'
    const titre = document.getElementById('titre-principal');
    titre.style.color = 'blue'; // Change la couleur du texte

    // Sélection des paragraphes avec la classe 'classe-exemple'
    const paragraphs = document.getElementsByClassName('classe-exemple');
    Array.from(paragraphs).forEach(p => {
        p.style.fontWeight = 'bold'; // Rend le texte en gras
    });

    // Sélection avec querySelector
    const premierParagraphe = document.querySelector('.classe-exemple');
    premierParagraphe.textContent = 'Texte modifié par JavaScript';
            

Astuces

  • Utilisez querySelector et querySelectorAll pour une plus grande flexibilité avec les sélecteurs CSS.
  • Transformez les résultats de getElementsByClassName ou getElementsByTagName en tableau avec Array.from() pour pouvoir utiliser les méthodes modernes comme forEach.
  • Privilégiez getElementById pour les sélections basées sur l'ID : rapide et spécifique.

Exercice : Sélectionner et manipuler le DOM

Dans cet exercice, vous allez utiliser différentes méthodes de sélection du DOM pour manipuler les éléments d'une page web. Suivez les étapes ci-dessous et vérifiez vos réponses dynamiquement !

Instructions

Vous avez le HTML suivant (visible dans la console en utilisant la solution) :


<div id="conteneur">
    <h1 id="titre-principal">Bienvenue</h1>
    <p class="classe-exemple">Premier paragraphe</p>
    <p class="classe-exemple">Deuxième paragraphe</p>
    <p>Paragraphe sans classe</p>
</div>
        

Votre mission :

  • Changer la couleur du texte de l'élément avec l'ID titre-principal en rouge.
  • Mettre les paragraphes ayant la classe classe-exemple en gras.
  • Ajouter un texte "Nouveau contenu" au paragraphe sans classe.

Votre code

Résultat

Bienvenue

Premier paragraphe

Deuxième paragraphe

Paragraphe sans classe

Modification du DOM

La modification du DOM permet d'ajouter, de supprimer ou de mettre à jour les éléments HTML d'une page web de manière dynamique. Grâce à JavaScript, il est possible de transformer complètement le contenu d'une page en réponse aux actions de l'utilisateur ou en fonction de certaines conditions.

Ajouter des éléments

Utilisez la méthode createElement pour créer de nouveaux éléments et la méthode appendChild ou insertBefore pour les insérer dans la structure du DOM.

Exemple :


// Créer un nouvel élément
const nouveauParagraphe = document.createElement('p');
nouveauParagraphe.textContent = 'Ceci est un nouveau paragraphe.';

// Sélectionner l'élément parent
const conteneur = document.getElementById('conteneur');

// Ajouter le paragraphe au conteneur
conteneur.appendChild(nouveauParagraphe);
            

Supprimer des éléments

Utilisez la méthode removeChild pour supprimer un élément enfant ou remove pour supprimer directement un élément.

Exemple :


// Sélectionner l'élément à supprimer
const paragrapheASupprimer = document.querySelector('.classe-exemple');

// Supprimer avec remove()
paragrapheASupprimer.remove();

// Supprimer avec removeChild()
const parent = paragrapheASupprimer.parentNode;
parent.removeChild(paragrapheASupprimer);
            

Modifier des éléments existants

Vous pouvez modifier le contenu, les attributs et les styles des éléments existants à l'aide de JavaScript.

Exemple :


// Modifier le texte d'un élément
const titre = document.querySelector('h1');
titre.textContent = 'Nouveau titre';

// Modifier un attribut
titre.setAttribute('id', 'nouveau-id');

// Modifier le style
titre.style.color = 'blue';
titre.style.fontSize = '24px';
            

Exemple visuel

Considérez le code HTML suivant :


<div id="conteneur">
    <h1>Bienvenue</h1>
    <p>Paragraphe existant</p>
</div>
        

Voici ce que vous pouvez réaliser en JavaScript :


// Ajouter un nouvel élément
const nouveauParagraphe = document.createElement('p');
nouveauParagraphe.textContent = 'Paragraphe ajouté dynamiquement.';
conteneur.appendChild(nouveauParagraphe);

// Modifier le texte du titre
titre.textContent = 'Titre modifié';

// Supprimer un paragraphe existant
paragrapheASupprimer.remove();
        

Astuces

  • Privilégiez remove() pour supprimer des éléments lorsque cela est pris en charge par les navigateurs.
  • Utilisez textContent plutôt que innerHTML pour des performances et une sécurité accrues.
  • Modifiez les styles directement via style ou en ajoutant/retirant des classes CSS avec classList.

Exercices : Modification du DOM

Pratiquez la modification du DOM à travers ces exercices interactifs. Suivez les instructions, exécutez votre code et observez les résultats dynamiquement.

Exercice 1 : Ajouter un élément

Créez un nouveau paragraphe avec le texte "Ceci est un paragraphe ajouté dynamiquement" et ajoutez-le à l'élément ayant l'ID conteneur-ex1.

Contenu initial


// Sélectionner le conteneur
const conteneur = document.getElementById('conteneur-ex1');

// Créer un nouvel élément
const paragraphe = document.createElement('p');
paragraphe.textContent = 'Ceci est un paragraphe ajouté dynamiquement.';

// Ajouter l'élément au DOM
conteneur.appendChild(paragraphe);

        

Exercice 2 : Supprimer un élément

Supprimez le paragraphe ayant la classe classe-a-supprimer dans l'élément avec l'ID conteneur-ex2.

Contenu initial

Paragraphe à supprimer


// Sélectionner l'élément à supprimer
const elementASupprimer = document.querySelector('.classe-a-supprimer');

// Supprimer l'élément
elementASupprimer.remove();

        

Exercice 3 : Modifier un élément

Changez le texte du titre (balise h4) à l'intérieur de l'élément avec l'ID conteneur-ex3 pour "Titre modifié dynamiquement". Changez également sa couleur en bleu.

Titre initial


// Sélectionner l'élément
const titre = document.querySelector('#conteneur-ex3 h4');

// Modifier le texte et le style
titre.textContent = 'Titre modifié dynamiquement';
titre.style.color = 'blue';

        

Événements

Les événements en JavaScript permettent de capturer les actions des utilisateurs (clics, frappes au clavier, soumissions de formulaires) ou du navigateur (chargement de la page, redimensionnement de la fenêtre, etc.). Ils sont essentiels pour rendre une page web interactive.

Types d'événements courants

  • click : Déclenché lorsqu'un élément est cliqué.
  • mouseover : Déclenché lorsque la souris passe au-dessus d'un élément.
  • keydown : Déclenché lorsqu'une touche du clavier est pressée.
  • submit : Déclenché lorsqu’un formulaire est soumis.
  • resize : Déclenché lorsqu’une fenêtre est redimensionnée.

Exemples interactifs

// Exemple d'événements JavaScript

// Changer la couleur d'un élément au clic
function changerCouleur() {
    document.getElementById("element").style.color = "blue";
}

// Afficher un message au survol
function afficherMessage() {
    document.getElementById("resultat-events").textContent = "Vous avez survolé l'élément !";
}

// Capturer une touche pressée
function afficherTouche(event) {
    document.getElementById("resultat-keydown").textContent = `Touche pressée : ${event.key}`;
}

// Capturer la soumission d'un formulaire
function gererSoumission(event) {
    event.preventDefault(); // Empêche le comportement par défaut de la soumission
    document.getElementById("resultat-submit").textContent = "Formulaire soumis !";
}

// Réagir au redimensionnement de la fenêtre
function afficherDimensions() {
    let largeur = window.innerWidth;
    let hauteur = window.innerHeight;
    document.getElementById("resultat-resize").textContent = `Dimensions : ${largeur}x${hauteur}`;
}
Survolez-moi pour un message !

Redimensionnez la fenêtre pour voir les dimensions :

JavaScript Avancé

Le JavaScript avancé est une étape essentielle pour les développeurs souhaitant maîtriser pleinement ce langage. Il va au-delà des bases pour se concentrer sur des concepts, outils et techniques qui permettent de créer des applications plus dynamiques, performantes et maintenables.

Dans cette section, vous apprendrez à utiliser des fonctionnalités modernes de JavaScript, à manipuler le DOM de manière avancée, et à gérer des interactions complexes avec des serveurs, des API et des données asynchrones. Vous serez également initié aux meilleures pratiques de développement pour produire un code propre, efficace et évolutif.

Contenu des cours

  • Promises et Async/Await : Gestion du code asynchrone pour effectuer des opérations comme les requêtes API sans bloquer l'exécution.
  • Classes et Programmation Orientée Objet (POO) : Structure de votre code avec des concepts avancés d’héritage et d’encapsulation.
  • Manipulation Avancée du DOM : Techniques pour sélectionner, modifier et manipuler les éléments HTML de manière performante.
  • Événements et Listeners : Gestion efficace des événements utilisateur pour améliorer l'interactivité.
  • Modules JavaScript : Organisation et réutilisation du code avec l'import/export de fonctionnalités.
  • Fetch API et Gestion des Données : Communication avec des serveurs pour récupérer et envoyer des données.
  • JSON et Web Storage : Manipulation des données JSON et stockage local avec LocalStorage ou SessionStorage.
  • Service Workers et Progressive Web Apps (PWA) : Création d’applications web modernes avec des fonctionnalités hors ligne.
  • Gestion des Erreurs et Debugging : Techniques pour identifier, prévenir et résoudre les erreurs efficacement.

Chaque cours inclut des exemples pratiques, des exercices interactifs, et des projets pour appliquer vos nouvelles compétences. À la fin de cette section, vous serez capable de développer des applications JavaScript avancées et professionnelles.

Classes

En JavaScript, les classes sont une fonctionnalité introduite avec ES6. Elles permettent de créer des modèles réutilisables pour structurer le code et organiser des fonctionnalités communes. Bien que les classes soient une abstraction, elles facilitent la gestion des données et des comportements liés à ces données.

Caractéristiques principales

  • Création de classes : Déclaration d'une classe avec le mot-clé class.
  • Constructeur : Une méthode spéciale appelée automatiquement lors de l'instanciation d'une classe.
  • Méthodes : Fonctionnalités définies à l'intérieur des classes pour effectuer des actions spécifiques.
  • Propriétés statiques : Propriétés directement accessibles via la classe, sans créer une instance.

Exemples pratiques

// Définir une classe
class Voiture {
    // Le constructeur initialise les propriétés
    constructor(marque, modele, annee) {
        this.marque = marque;
        this.modele = modele;
        this.annee = annee;
    }

    // Méthode pour afficher les détails de la voiture
    afficherDetails() {
        return `Voiture : ${this.marque} ${this.modele}, Année : ${this.annee}`;
    }

    // Propriété statique
    static categorie = "Véhicule";

    // Méthode statique
    static comparer(voiture1, voiture2) {
        return voiture1.annee > voiture2.annee ? voiture1 : voiture2;
    }
}

// Instanciation d'une classe
let voiture1 = new Voiture("Toyota", "Corolla", 2020);
let voiture2 = new Voiture("Honda", "Civic", 2018);

// Utiliser une méthode
console.log(voiture1.afficherDetails()); // Voiture : Toyota Corolla, Année : 2020

// Accéder à une propriété statique
console.log(Voiture.categorie); // Véhicule

// Utiliser une méthode statique
let plusRecente = Voiture.comparer(voiture1, voiture2);
console.log(plusRecente.afficherDetails()); // Voiture : Toyota Corolla, Année : 2020

Cas d'utilisation pratiques

Les classes peuvent être utilisées pour :

  • Modéliser des entités : Créer des modèles simples pour structurer les données, comme des produits, des utilisateurs ou des véhicules.
  • Créer des collections réutilisables : Définir des fonctionnalités standardisées pour des groupes similaires d'objets.
  • Ajouter des méthodes spécifiques : Faciliter les opérations fréquentes sur des ensembles de données.
  • Centraliser des propriétés ou méthodes : Utiliser des méthodes ou propriétés statiques pour des valeurs communes.

Programmation Orientée Objet (POO)

Après avoir exploré les classes, il est important de comprendre leur rôle dans un paradigme plus large : la Programmation Orientée Objet (POO). Les classes sont un outil de la POO, mais la POO va bien au-delà en proposant une manière de penser et de structurer votre code en JavaScript.

Différence entre les Classes et la POO

  • Classes : Une abstraction qui permet de créer des modèles d'objets. Elles se concentrent sur la création et la gestion de structures spécifiques.
  • POO : Un paradigme de programmation qui repose sur des concepts comme l'encapsulation, l'héritage, et le polymorphisme. La POO utilise les classes et les objets pour structurer le code, favoriser la réutilisation et faciliter la maintenance.

Principes fondamentaux de la POO

La POO repose sur quatre piliers principaux :

  • Encapsulation : Regrouper les données (propriétés) et les comportements (méthodes) dans une entité appelée objet.
  • Héritage : Créer des relations entre les classes pour partager des propriétés et des méthodes communes.
  • Polymorphisme : Permettre à des méthodes ou des objets de prendre plusieurs formes, souvent en redéfinissant ou en surchargeant des méthodes.
  • Abstraction : Cacher les détails complexes pour ne montrer que l'essentiel à l'utilisateur.

Exemples pratiques

// Exemple de POO en JavaScript

// Classe de base (Encapsulation)
class Animal {
    constructor(nom, type) {
        this.nom = nom;
        this.type = type;
    }

    // Méthode générique
    decrire() {
        return `${this.nom} est un ${this.type}.`;
    }
}

// Héritage : Classe spécifique qui hérite de la classe Animal
class Chien extends Animal {
    // Ajout d'une méthode spécifique
    aboyer() {
        return `Woof! Je suis ${this.nom}.`;
    }
}

// Polymorphisme : Redéfinition de la méthode decrire
class Chat extends Animal {
    decrire() {
        return `${this.nom} est un chat très mignon.`;
    }
}

// Instanciation d'objets
let animal1 = new Animal("Daisy", "oiseau");
let chien1 = new Chien("Max", "chien");
let chat1 = new Chat("Milo", "chat");

// Utilisation des méthodes
console.log(animal1.decrire()); // Daisy est un oiseau.
console.log(chien1.decrire());  // Max est un chien.
console.log(chien1.aboyer());  // Woof! Je suis Max.
console.log(chat1.decrire());  // Milo est un chat très mignon.

Concepts avancés

  • Constructeurs parent et super : Utilisation du mot-clé super pour accéder au constructeur ou aux méthodes d’une classe parente.
  • Getters et Setters : Méthodes pour accéder ou modifier des propriétés tout en encapsulant la logique.
  • Composition : Utilisation d'autres objets au lieu d'hériter d'une classe (concept has-a).

Exemples supplémentaires

// Exemple avec super et getters/setters

class Personne {
    constructor(nom, age) {
        this.nom = nom;
        this.age = age;
    }

    // Getter pour le nom complet
    get nomComplet() {
        return `Nom complet : ${this.nom}`;
    }

    // Setter pour changer le nom
    set changerNom(nouveauNom) {
        this.nom = nouveauNom;
    }
}

// Héritage et utilisation de super
class Etudiant extends Personne {
    constructor(nom, age, programme) {
        super(nom, age); // Appelle le constructeur parent
        this.programme = programme;
    }

    decrire() {
        return `${this.nom}, ${this.age} ans, étudie ${this.programme}.`;
    }
}

// Instanciation
let etudiant1 = new Etudiant("Alice", 22, "Informatique");

// Utilisation
console.log(etudiant1.decrire());  // Alice, 22 ans, étudie Informatique.
etudiant1.changerNom = "Alicia";
console.log(etudiant1.nomComplet); // Nom complet : Alicia

Promises

Les Promises en JavaScript sont un mécanisme pour gérer les opérations asynchrones. Elles permettent d’exécuter du code après l’achèvement d’une tâche, en évitant les fameux "callbacks hell" et en rendant le code plus lisible et maintenable.

Pourquoi utiliser les Promises ?

  • Simplifier les opérations asynchrones : Les Promises permettent de chaîner des opérations asynchrones de manière claire.
  • Éviter les callbacks imbriqués : En remplaçant les callbacks imbriqués par des méthodes comme then et catch.
  • Gestion efficace des erreurs : Les Promises capturent les erreurs sur tout le chaînage via catch.

Structure d’une Promise

Une Promise est un objet qui représente une valeur qui peut être disponible maintenant, dans le futur, ou jamais. Elle a trois états possibles :

  • Pending : La Promise est en attente (opération en cours).
  • Fulfilled : La Promise est résolue avec succès.
  • Rejected : La Promise a échoué.

Création et utilisation de Promises

// Création d'une Promise
const maPromise = new Promise((resolve, reject) => {
    // Simule une opération asynchrone
    let operationReussie = true;

    // Après 2 secondes, on décide du résultat
    setTimeout(() => {
        if (operationReussie) {
            resolve("Opération réussie !");
        } else {
            reject("Erreur lors de l'opération.");
        }
    }, 2000);
});

// Consommer une Promise
maPromise
    .then((resultat) => {
        console.log(resultat); // "Opération réussie !"
    })
    .catch((erreur) => {
        console.error(erreur); // "Erreur lors de l'opération."
    })
    .finally(() => {
        console.log("Opération terminée.");
    });

Méthodes principales des Promises

  • then : Exécute une fonction lorsque la Promise est résolue.
  • catch : Exécute une fonction lorsque la Promise est rejetée.
  • finally : Exécute une fonction une fois que la Promise est terminée, qu'elle soit résolue ou rejetée.
  • Promise.all : Attend que toutes les Promises passées soient résolues ou qu’une échoue.
  • Promise.race : Renvoie la première Promise résolue ou rejetée.
  • Promise.allSettled : Attend que toutes les Promises soient terminées, quelle que soit leur issue.
  • Promise.any : Renvoie la première Promise résolue, ignore les rejets.

Exemples avancés

// Exemple avec Promise.all
const promesse1 = new Promise((resolve) => setTimeout(resolve, 1000, "Promise 1 résolue"));
const promesse2 = new Promise((resolve) => setTimeout(resolve, 2000, "Promise 2 résolue"));
const promesse3 = new Promise((resolve, reject) => setTimeout(reject, 1500, "Promise 3 rejetée"));

Promise.all([promesse1, promesse2, promesse3])
    .then((resultats) => {
        console.log(resultats); // ["Promise 1 résolue", "Promise 2 résolue"]
    })
    .catch((erreur) => {
        console.error(erreur); // "Promise 3 rejetée"
    });

// Exemple avec Promise.race
Promise.race([promesse1, promesse2, promesse3])
    .then((resultat) => {
        console.log(resultat); // "Promise 1 résolue"
    })
    .catch((erreur) => {
        console.error(erreur); // Si la première est rejetée
    });

Cas d’utilisation courants

Les Promises sont utilisées dans divers scénarios asynchrones :

  • Requêtes API : Récupération de données depuis un serveur avec fetch.
  • Chargement de ressources : Téléchargement d'images ou de fichiers.
  • Animations : Attente de la fin d’une animation ou d’une transition.
  • Opérations complexes : Exécution de plusieurs tâches asynchrones en parallèle.

Async/Await

Async/Await est une syntaxe introduite avec ES8 (ECMAScript 2017) pour simplifier la gestion des opérations asynchrones. Elle repose sur les Promises, mais rend le code plus lisible et facile à écrire, semblable à du code synchrone.

Pourquoi utiliser Async/Await ?

  • Lisibilité : Simplifie les chaînes de .then et évite les imbrications complexes.
  • Gestion des erreurs : Permet de capturer les erreurs avec un bloc try/catch, facilitant le débogage.
  • Code synchrone-like : Écrit des fonctions asynchrones de manière séquentielle, ce qui est intuitif.

Concepts fondamentaux

  • async : Déclare une fonction asynchrone. Une fonction asynchrone renvoie toujours une Promise.
  • await : Suspend l’exécution d’une fonction asynchrone jusqu'à ce qu'une Promise soit résolue ou rejetée.

Structure d’Async/Await

// Définir une fonction asynchrone
async function exempleAsync() {
    // Simuler une opération asynchrone avec une Promise
    let resultat = await new Promise((resolve) => {
        setTimeout(() => resolve("Opération terminée !"), 2000);
    });

    console.log(resultat); // "Opération terminée !"
}

// Appeler une fonction asynchrone
exempleAsync();

Gestion des erreurs avec Async/Await

Les erreurs dans les fonctions asynchrones peuvent être capturées avec un bloc try/catch :

// Exemple de gestion d'erreur
async function operationAvecErreur() {
    try {
        let resultat = await new Promise((_, reject) => {
            setTimeout(() => reject("Une erreur est survenue."), 2000);
        });

        console.log(resultat); // Ne sera pas exécuté
    } catch (erreur) {
        console.error(erreur); // "Une erreur est survenue."
    }
}

operationAvecErreur();

Combinaison d’Async/Await avec des boucles

Async/Await peut être utilisé dans des boucles pour gérer des opérations répétées de manière séquentielle :

// Exécution séquentielle avec une boucle
async function traiterTableau() {
    let elements = ["A", "B", "C"];

    for (let element of elements) {
        await new Promise((resolve) => {
            setTimeout(() => {
                console.log(`Traitement de ${element}`);
                resolve();
            }, 1000);
        });
    }

    console.log("Tous les éléments ont été traités.");
}

traiterTableau();

Exemples avancés

Async/Await peut être combiné avec des Promises pour exécuter des tâches simultanées et séquentielles :

// Exécution parallèle avec Promise.all
async function executionParallele() {
    let promesse1 = new Promise((resolve) => setTimeout(resolve, 1000, "Tâche 1 terminée"));
    let promesse2 = new Promise((resolve) => setTimeout(resolve, 2000, "Tâche 2 terminée"));

    let resultats = await Promise.all([promesse1, promesse2]);

    console.log(resultats); // ["Tâche 1 terminée", "Tâche 2 terminée"]
}

executionParallele();

Cas d’utilisation courants

  • Requêtes API : Utilisation de fetch pour récupérer des données de manière asynchrone.
  • Animations : Synchronisation d'animations ou de transitions.
  • Flux de traitement : Exécution de plusieurs étapes dépendantes de manière séquentielle.
  • Opérations parallèles : Gérer plusieurs tâches simultanées avec Promise.all.

Callbacks

Les callbacks sont des fonctions passées en argument à une autre fonction, qui sont ensuite exécutées à l’intérieur de cette fonction. Ils permettent d’exécuter du code de manière asynchrone ou en réponse à un événement.

Pourquoi utiliser des callbacks ?

  • Flexibilité : Vous pouvez passer différentes fonctions pour modifier le comportement d'une fonction principale.
  • Asynchronisme : Les callbacks sont souvent utilisés pour gérer des opérations asynchrones, comme les requêtes API.

Exemple simple

// Exemple de callback simple
function afficherMessage(message, callback) {
    console.log("Message principal :", message);
    callback(); // Appelle la fonction callback
}

// Fonction callback
function afficherFin() {
    console.log("Opération terminée.");
}

// Appel de la fonction avec un callback
afficherMessage("Bonjour, monde !", afficherFin);

Gestion des opérations asynchrones

Les callbacks sont souvent utilisés pour gérer des opérations comme des délais ou des requêtes asynchrones :

// Exemple asynchrone avec setTimeout
function executerAvecDelai(callback) {
    console.log("Début de l'opération...");
    setTimeout(() => {
        callback(); // Exécute le callback après 2 secondes
    }, 2000);
}

// Callback
function finDelai() {
    console.log("Opération terminée après 2 secondes.");
}

executerAvecDelai(finDelai);

Closures

Une closure est une fonction qui se souvient de son environnement lexical, même lorsque la fonction est exécutée en dehors de cet environnement. Cela signifie qu’une fonction interne peut accéder aux variables de sa fonction parente, même après que la fonction parente ait terminé son exécution.

Pourquoi utiliser les closures ?

  • Encapsulation : Permet de créer des fonctions avec des variables privées.
  • Mémoire persistante : Les closures permettent de conserver l’état des variables entre plusieurs appels.

Exemple de base

// Exemple simple de closure
function creerCompteur() {
    let compteur = 0;

    // Retourne une fonction qui utilise la variable compteur
    return function() {
        compteur++;
        console.log(`Compteur : ${compteur}`);
    };
}

// Utilisation
const incrementer = creerCompteur();
incrementer(); // Compteur : 1
incrementer(); // Compteur : 2
incrementer(); // Compteur : 3

Encapsulation avec closures

Les closures sont souvent utilisées pour encapsuler des données dans un environnement privé :

// Exemple d'encapsulation avec une closure
function banqueCompte(initial) {
    let solde = initial;

    // Retourne des fonctions pour gérer le compte
    return {
        deposer(montant) {
            solde += montant;
            console.log(`Solde après dépôt : ${solde}€`);
        },
        retirer(montant) {
            if (montant > solde) {
                console.log("Fonds insuffisants.");
            } else {
                solde -= montant;
                console.log(`Solde après retrait : ${solde}€`);
            }
        },
        consulter() {
            console.log(`Solde actuel : ${solde}€`);
        }
    };
}

// Utilisation
const monCompte = banqueCompte(100);
monCompte.deposer(50); // Solde après dépôt : 150€
monCompte.retirer(30); // Solde après retrait : 120€
monCompte.consulter(); // Solde actuel : 120€

Cas d’utilisation des closures

  • Fonctions mémorisées : Créer des fonctions avec un état persistant (par ex. compteurs).
  • Encapsulation : Protéger les données en limitant leur accès via des méthodes.
  • Gestion d'événements : Utiliser des closures pour conserver des valeurs dans des gestionnaires d’événements.

JSON (JavaScript Object Notation)

JSON (JavaScript Object Notation) est un format de données léger, facile à lire et à écrire pour les humains, et facile à analyser et générer pour les machines. JSON est largement utilisé pour échanger des données entre un client (navigateur) et un serveur.

Pourquoi utiliser JSON ?

  • Interopérabilité : JSON est pris en charge par presque tous les langages de programmation.
  • Format léger : JSON est compact et facile à transporter sur le réseau.
  • Facilité de lecture : Sa structure est intuitive et proche de celle des objets JavaScript.
  • Standard web : JSON est devenu un standard pour l’échange de données dans les API RESTful.

Structure de JSON

JSON est constitué de paires clé-valeur, et il peut contenir :

  • Objets : Représentés par des accolades {}.
  • Tableaux : Représentés par des crochets [].
  • Types de données : String, Number, Boolean, Array, Object, null.

Exemple d’un fichier JSON

{
    "nom": "Alice",
    "age": 30,
    "estAdmin": false,
    "hobbies": ["lecture", "voyage", "cuisine"],
    "adresse": {
        "ville": "Paris",
        "codePostal": 75001
    }
}

Manipulation de JSON en JavaScript

JavaScript offre deux méthodes principales pour travailler avec JSON :

  • JSON.stringify(objet) : Convertit un objet JavaScript en chaîne JSON.
  • JSON.parse(jsonString) : Convertit une chaîne JSON en objet JavaScript.

Exemple d’utilisation

// Exemple d'utilisation de JSON.stringify et JSON.parse

// Un objet JavaScript
const utilisateur = {
    nom: "Alice",
    age: 30,
    hobbies: ["lecture", "voyage"],
    estAdmin: false
};

// Convertir l'objet en JSON
const jsonString = JSON.stringify(utilisateur);
console.log(jsonString);
/*
    {"nom":"Alice","age":30,"hobbies":["lecture","voyage"],"estAdmin":false}
*/

// Convertir une chaîne JSON en objet
const jsonObjet = JSON.parse(jsonString);
console.log(jsonObjet);
/*
    {
        nom: "Alice",
        age: 30,
        hobbies: ["lecture", "voyage"],
        estAdmin: false
    }
*/

Requêtes HTTP et JSON

JSON est fréquemment utilisé dans les requêtes API pour envoyer et recevoir des données. Voici un exemple avec fetch :

// Exemple d'utilisation de JSON avec fetch
async function obtenirUtilisateurs() {
    try {
        // Effectuer une requête GET
        const response = await fetch("https://jsonplaceholder.typicode.com/users");
        // Convertir la réponse en JSON
        const utilisateurs = await response.json();
        console.log(utilisateurs);
    } catch (erreur) {
        console.error("Erreur lors de la récupération des utilisateurs :", erreur);
    }
}

obtenirUtilisateurs();

Cas d’utilisation courants

  • APIs : Échanger des données entre un client et un serveur.
  • Stockage local : Stocker des données dans localStorage ou sessionStorage.
  • Configuration : Utiliser JSON pour des fichiers de configuration.
  • Mock de données : Simuler des réponses de serveur pour les tests.

Bonnes pratiques avec JSON

  • Vérifiez toujours la validité de votre JSON avec des outils comme JSONLint.
  • Utilisez try/catch pour gérer les erreurs lors du parsing JSON.
  • Évitez les références circulaires dans vos objets, car elles provoquent des erreurs avec JSON.stringify.
  • Minimisez vos données pour réduire la taille de vos requêtes réseau.

Modules en JavaScript

Les modules en JavaScript permettent de mieux organiser le code en le divisant en plusieurs fichiers. Cela permet de maintenir un code plus propre, réutilisable et facile à déboguer. Les modules facilitent l’importation et l’exportation de fonctionnalités entre différentes parties de l’application.

Pourquoi utiliser des modules ?

  • Modularité : Divisez le code en blocs réutilisables pour éviter la duplication.
  • Maintenance : Facilite la gestion du code à long terme en le rendant plus lisible et organisé.
  • Scalabilité : Permet de développer des applications plus complexes avec une architecture bien structurée.
  • Réutilisation : Permet de partager du code entre différents projets ou modules.

Les types de modules en JavaScript

En JavaScript, il existe deux principaux systèmes pour gérer les modules :

  • Modules ES6 : La syntaxe native de JavaScript pour l'importation et l'exportation de modules.
  • CommonJS : Un système de modules principalement utilisé côté serveur (Node.js).

Modules ES6

Les modules ES6 sont maintenant la norme pour la gestion des modules en JavaScript, notamment dans les navigateurs modernes et les outils de bundling comme Webpack.

  • export : Permet d'exporter une fonction, un objet, ou une variable d'un module.
  • import : Permet d'importer des fonctions, objets ou variables depuis un autre module.

Exemple d’utilisation des Modules ES6

Imaginons que vous avez deux fichiers : calcul.js et app.js.

Fichier calcul.js
// Fichier calcul.js - Contient des fonctions pour des calculs

// Exportation d'une fonction
export function addition(a, b) {
    return a + b;
}

export function soustraction(a, b) {
    return a - b;
}

export const pi = 3.14;
Fichier app.js
// Fichier app.js - Utilise les fonctions du module calcul.js

// Importation des fonctions et variables depuis calcul.js
import { addition, soustraction, pi } from "./calcul.js";

console.log(addition(5, 3));  // 8
console.log(soustraction(5, 3));  // 2
console.log(pi);  // 3.14

Importation et exportation par défaut

Un module peut également exporter un seul élément par défaut à l'aide de export default. Cela simplifie l'importation d'un module avec un seul export.

Exemple d'exportation par défaut
// Fichier calcul.js - Exportation par défaut
export default function multiplication(a, b) {
    return a * b;
}
Importation par défaut
// Fichier app.js - Importation de la fonction par défaut
import multiplication from "./calcul.js";

console.log(multiplication(5, 3));  // 15

Cas d’utilisation des Modules

  • Organiser le code : Diviser un code complexe en plusieurs fichiers pour améliorer la lisibilité et la maintenance.
  • Réutilisation : Créer des modules réutilisables pour partager du code entre plusieurs projets.
  • Gestion des dépendances : Utiliser des modules pour gérer des bibliothèques externes avec des outils comme NPM.
  • Scalabilité : Développer des applications complexes en répartissant les responsabilités entre différents modules.

Utilisation des Modules avec un Bundler (Webpack)

Les modules ES6 sont très efficaces dans un environnement de développement avec un bundler comme Webpack. Ce dernier permet de regrouper plusieurs fichiers JavaScript en un seul fichier pour optimiser les performances du site.

  • Installation : Vous pouvez installer Webpack et ses dépendances via npm ou yarn.
  • Configuration : Utilisez un fichier de configuration pour définir les points d’entrée et de sortie des fichiers modules.
  • Utilisation : Après avoir configuré Webpack, vous pouvez importez vos fichiers JavaScript et ils seront automatiquement regroupés.

Conclusion

Les modules JavaScript permettent de structurer et de maintenir efficacement des applications complexes. Utiliser la syntaxe des modules ES6, combinée à des outils modernes comme Webpack, rend le code plus modulaire, réutilisable et optimisé.

API Fetch

Fetch est une interface moderne introduite avec ES6 pour effectuer des requêtes HTTP. Elle remplace l'ancienne méthode XMLHttpRequest, offrant une syntaxe plus simple et intuitive basée sur des Promises.

Pourquoi utiliser l'API Fetch ?

  • Simplicité : Syntaxe claire et lisible pour effectuer des requêtes asynchrones.
  • Basée sur des Promises : Compatible avec then, catch, et async/await.
  • Supporte les options avancées : En-têtes personnalisés, méthodes HTTP (GET, POST, PUT, DELETE, etc.), gestion des corps de requêtes.

Syntaxe de base

La méthode fetch() retourne une Promise qui se résout avec une réponse HTTP (ou est rejetée en cas d'erreur réseau).

// Exemple simple avec fetch
fetch("https://jsonplaceholder.typicode.com/posts")
    .then((response) => {
        // Vérifie si la réponse est OK
        if (!response.ok) {
            throw new Error(`Erreur HTTP ! Statut : ${response.status}`);
        }
        return response.json(); // Convertit en JSON
    })
    .then((data) => {
        console.log(data); // Affiche les données reçues
    })
    .catch((error) => {
        console.error("Erreur lors de la requête :", error);
    });

Utilisation avec async/await

Pour rendre le code encore plus lisible, vous pouvez utiliser async/await avec Fetch :

// Exemple avec async/await
async function obtenirPosts() {
    try {
        // Effectuer une requête GET
        const response = await fetch("https://jsonplaceholder.typicode.com/posts");
        // Vérifie si la réponse est OK
        if (!response.ok) {
            throw new Error(`Erreur HTTP ! Statut : ${response.status}`);
        }
        // Convertit la réponse en JSON
        const data = await response.json();
        console.log(data); // Affiche les données
    } catch (erreur) {
        console.error("Erreur :", erreur);
    }
}

obtenirPosts();

Options avancées de Fetch

Fetch permet de configurer la requête avec un deuxième argument contenant des options :

// Exemple d'envoi de données avec Fetch
async function envoyerDonnees() {
    const donnees = {
        titre: "Nouveau post",
        contenu: "Ceci est un exemple de contenu."
    };

    try {
        const response = await fetch("https://jsonplaceholder.typicode.com/posts", {
            // Configuration de la requête
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(donnees) // Corps de la requête
        });

        if (!response.ok) {
            throw new Error(`Erreur HTTP : ${response.status}`);
        }

        const result = await response.json();
        console.log("Données envoyées avec succès :", result);
    } catch (erreur) {
        console.error("Erreur :", erreur);
    }
}

envoyerDonnees();

Cas d’utilisation courants

  • Requêtes API : Communication avec un serveur pour récupérer ou envoyer des données.
  • Chargement dynamique : Charger des contenus dynamiques sans recharger la page (AJAX).
  • Authentification : Envoyer des identifiants utilisateur pour se connecter à un service.
  • Opérations CRUD : Créer, lire, mettre à jour ou supprimer des ressources sur un serveur.

Bonnes pratiques

  • Vérifiez toujours le statut de la réponse avec response.ok avant de traiter les données.
  • Utilisez try/catch pour gérer les erreurs, notamment les problèmes de réseau ou de serveur.
  • Spécifiez les en-têtes nécessaires pour les requêtes POST, PUT ou DELETE.
  • Minimisez les requêtes réseau en regroupant les données nécessaires.

JavaScript Expert

Le niveau expert en JavaScript est destiné aux développeurs souhaitant maîtriser les aspects les plus avancés et les techniques professionnelles du langage. Ce niveau explore des fonctionnalités modernes et des concepts complexes pour développer des applications hautement performantes et évolutives.

Dans cette section, vous apprendrez à optimiser le traitement des données, gérer des opérations complexes avec les workers, utiliser des fonctionnalités avancées de JavaScript ES6+, et améliorer la robustesse de vos applications grâce aux tests unitaires et à la gestion des erreurs. Vous explorerez également des concepts essentiels pour les Progressive Web Apps (PWA) et les environnements hors ligne.

Contenu des cours

  • Web Storage : Manipulation efficace des données stockées localement avec localStorage et sessionStorage, pour des fonctionnalités telles que les sauvegardes automatiques et les préférences utilisateur.
  • Programmation Orientée Objet Expert : Exploration approfondie de la POO, incluant l’héritage complexe, les mixins, et les design patterns en JavaScript.
  • Web Workers : Utilisation des threads JavaScript pour exécuter des tâches intensives en arrière-plan sans bloquer l’interface utilisateur.
  • Gestion des Erreurs et Debugging : Techniques avancées pour détecter, capturer et résoudre efficacement les erreurs dans des applications complexes.
  • Service Workers et PWA : Développement d'applications web modernes capables de fonctionner hors ligne, avec des mises à jour automatiques et des notifications push.
  • Synthaxe Moderne ES6+ : Utilisation des fonctionnalités avancées de JavaScript telles que les modules, les destructurations, les spread/rest operators, et les itérateurs.
  • Tests Unitaires : Introduction aux frameworks comme Jest ou Mocha pour écrire et automatiser des tests unitaires, garantissant la qualité du code.

Chaque cours est accompagné d'exemples pratiques, de défis interactifs, et de projets avancés pour mettre en pratique vos connaissances. À la fin de cette section, vous serez équipé pour créer des applications JavaScript professionnelles, optimisées et robustes, capables de répondre aux exigences les plus complexes.

Web Storage

Le Web Storage est une API JavaScript qui permet de stocker des données côté client directement dans le navigateur. Il se compose de deux types principaux de stockage : localStorage et sessionStorage. Ces méthodes offrent une manière simple et efficace de conserver des informations utilisateur pour des applications web.

Pourquoi utiliser le Web Storage ?

  • Persistant : Les données peuvent persister après le rechargement ou la fermeture du navigateur (avec localStorage).
  • Accessible : Les données sont facilement accessibles via une simple API JavaScript.
  • Sécurisé : Les données sont spécifiques au domaine et ne sont pas envoyées au serveur automatiquement.
  • Rapide : Idéal pour stocker des préférences utilisateur, des jetons de session, ou des données temporaires.

Différences entre localStorage et sessionStorage

Caractéristique localStorage sessionStorage
Persistance Les données persistent après la fermeture du navigateur. Les données sont supprimées à la fermeture de l’onglet ou de la fenêtre.
Portée Partagée entre tous les onglets et fenêtres du même domaine. Spécifique à l’onglet ou la fenêtre active.
Taille 5 à 10 Mo (selon le navigateur). 5 à 10 Mo (selon le navigateur).

Fonctionnalités principales

  • setItem(key, value) : Enregistre une donnée avec une clé.
  • getItem(key) : Récupère une donnée à partir d'une clé.
  • removeItem(key) : Supprime une donnée à partir d'une clé.
  • clear() : Supprime toutes les données stockées.
  • length : Retourne le nombre d'éléments stockés.

Exemples pratiques

Stocker et récupérer des données
// Stocker une donnée
localStorage.setItem("utilisateur", "Alice");

// Récupérer une donnée
const utilisateur = localStorage.getItem("utilisateur");
console.log(utilisateur); // Alice
Supprimer une donnée ou tout effacer
// Supprimer une donnée
localStorage.removeItem("utilisateur");

// Supprimer toutes les données
localStorage.clear();
Manipuler des objets avec Web Storage
// Stocker un objet après sérialisation
const utilisateur = {
    nom: "Alice",
    age: 30,
    estAdmin: true
};

localStorage.setItem("utilisateur", JSON.stringify(utilisateur));

// Récupérer et désérialiser l'objet
const utilisateurRecupere = JSON.parse(localStorage.getItem("utilisateur"));
console.log(utilisateurRecupere); // { nom: "Alice", age: 30, estAdmin: true }

Cas d’utilisation courants

  • Jetons de session : Stocker des tokens pour l’authentification (ex : OAuth).
  • Préférences utilisateur : Sauvegarder les thèmes, langues ou paramètres de personnalisation.
  • Panier d’achat : Conserver les articles ajoutés au panier dans une application e-commerce.
  • Statistiques locales : Enregistrer des données non sensibles pour l’analyse hors ligne.

Bonnes pratiques

  • Utilisez JSON.stringify pour stocker des objets et JSON.parse pour les récupérer.
  • Évitez de stocker des données sensibles comme des mots de passe ou des informations bancaires.
  • Nettoyez régulièrement les données inutilisées pour optimiser l'espace.
  • Utilisez sessionStorage pour les données temporaires spécifiques à un onglet.

Programmation Orientée Objet (POO) Expert

La Programmation Orientée Objet (POO) au niveau expert en JavaScript consiste à maîtriser des concepts avancés tels que l’héritage complexe, les mixins, les design patterns, et l’utilisation efficace des classes dans des applications scalables et maintenables. Ce niveau approfondit les bases pour concevoir des systèmes robustes avec une architecture modulaire.

Concepts avancés de la POO

  • Héritage complexe : Implémentation d'héritages multiples avec des classes et des prototypes.
  • Mixins : Ajout de fonctionnalités partagées à plusieurs classes sans héritage direct.
  • Encapsulation avancée : Gestion des membres privés et protégés dans les classes.
  • Polymorphisme : Permet d’utiliser une interface commune pour différentes implémentations.
  • Design Patterns : Application de modèles comme Singleton, Factory, ou Observer.

Héritage complexe

En JavaScript, l’héritage est basé sur les prototypes, mais avec les classes ES6, il est simplifié et plus intuitif.

// Exemple d'héritage complexe
class Animal {
    constructor(nom) {
        this.nom = nom;
    }

    parler() {
        console.log(`${this.nom} fait un bruit.`);
    }
}

class Chien extends Animal {
    parler() {
        console.log(`${this.nom} aboie.`);
    }
}

class Chat extends Animal {
    parler() {
        console.log(`${this.nom} miaule.`);
    }
}

// Utilisation
const rex = new Chien("Rex");
rex.parler(); // Rex aboie.

const felix = new Chat("Félix");
felix.parler(); // Félix miaule.

Mixins

Les mixins permettent d’ajouter des fonctionnalités à plusieurs classes sans utiliser l’héritage direct.

// Exemple de Mixin
const Volant = {
    voler() {
        console.log(`${this.nom} peut voler !`);
    }
};

class Oiseau {
    constructor(nom) {
        this.nom = nom;
    }
}

Object.assign(Oiseau.prototype, Volant);

// Utilisation
const aigle = new Oiseau("Aigle");
aigle.voler(); // Aigle peut voler !

Encapsulation avancée

Les membres privés ou protégés sont essentiels pour contrôler l’accès aux propriétés ou méthodes d’une classe. En JavaScript, cela peut être réalisé avec des symboles ou le mot-clé #.

// Exemple d'encapsulation avec membres privés
class CompteBancaire {
    constructor(soldeInitial) {
        this.#solde = soldeInitial; // Membres privés
    }

    #verifierFonds(montant) {
        return montant <= this.#solde;
    }

    retirer(montant) {
        if (this.#verifierFonds(montant)) {
            this.#solde -= montant;
            console.log(`Retrait de ${montant}€. Solde restant : ${this.#solde}€`);
        } else {
            console.log("Fonds insuffisants.");
        }
    }
}

// Utilisation
const compte = new CompteBancaire(1000);
compte.retirer(200); // Retrait de 200€. Solde restant : 800€
compte.retirer(900); // Fonds insuffisants.

Polymorphisme

Le polymorphisme permet d’appeler des méthodes sur des objets dérivés, en garantissant un comportement spécifique à chaque sous-classe.

// Exemple de polymorphisme
class Forme {
    aire() {
        throw new Error("Méthode non implémentée.");
    }
}

class Cercle extends Forme {
    constructor(rayon) {
        super();
        this.rayon = rayon;
    }

    aire() {
        return Math.PI * this.rayon ** 2;
    }
}

class Rectangle extends Forme {
    constructor(largeur, hauteur) {
        super();
        this.largeur = largeur;
        this.hauteur = hauteur;
    }

    aire() {
        return this.largeur * this.hauteur;
    }
}

// Utilisation
const formes = [
    new Cercle(5),
    new Rectangle(4, 6)
];

formes.forEach((forme) => {
    console.log(`Aire : ${forme.aire()}`);
});

Design Patterns

  • Singleton : Créer une seule instance d’une classe pour tout un projet.
  • Factory : Générer des objets sans spécifier leur classe exacte.
  • Observer : Permet à un objet de notifier automatiquement les changements à ses abonnés.

Web Workers

Les Web Workers sont des scripts qui permettent d’exécuter du code JavaScript en arrière-plan, indépendamment du thread principal du navigateur. Cela empêche les tâches intensives (comme les calculs complexes ou les requêtes longues) de bloquer l’interface utilisateur, offrant une meilleure expérience utilisateur.

Pourquoi utiliser les Web Workers ?

  • Performances : Exécuter des tâches lourdes sans affecter l’interactivité de la page.
  • Multi-threading : Permet de tirer parti du traitement parallèle.
  • Expérience utilisateur : Maintenir une interface réactive tout en exécutant des calculs ou des traitements en arrière-plan.

Types de Web Workers

  • Dedicated Workers : Associés à un seul script principal, parfaits pour des tâches spécifiques.
  • Shared Workers : Partagés entre plusieurs scripts principaux, utile pour gérer des ressources communes.
  • Service Workers : Utilisés pour les Progressive Web Apps (PWA), permettant des fonctionnalités comme le cache hors ligne et les notifications push.

Créer et utiliser un Web Worker

Un Web Worker est défini dans un fichier JavaScript séparé. Voici un exemple complet :

Fichier du Worker (worker.js)
// worker.js - Fichier exécuté en arrière-plan

// Réception d'un message depuis le thread principal
self.addEventListener("message", (event) => {
    const nombre = event.data;

    // Calcul intensif
    let resultat = 0;
    for (let i = 1; i <= nombre; i++) {
        resultat += i;
    }

    // Envoi du résultat au thread principal
    self.postMessage(resultat);
});
Script principal (main.js)
// main.js - Script principal

// Création d'un Worker
const worker = new Worker("worker.js");

// Envoi d'un message au Worker
worker.postMessage(1000000);

// Réception du résultat
worker.addEventListener("message", (event) => {
    console.log(`Résultat : ${event.data}`);
});

// Gestion des erreurs
worker.addEventListener("error", (error) => {
    console.error(`Erreur dans le Worker : ${error.message}`);
});

Shared Workers

Les Shared Workers peuvent être partagés entre plusieurs fenêtres ou onglets du même domaine :

Fichier Shared Worker (shared-worker.js)
// shared-worker.js

// Gestion des connexions multiples
self.addEventListener("connect", (event) => {
    const port = event.ports[0];

    port.addEventListener("message", (e) => {
        const data = e.data;
        port.postMessage(`Données reçues : ${data}`);
    });

    port.start();
});
Utilisation d’un Shared Worker (main.js)
// main.js

// Création d'un Shared Worker
const sharedWorker = new SharedWorker("shared-worker.js");
const port = sharedWorker.port;

// Envoi de données
port.postMessage("Hello depuis le script principal");

// Réception de données
port.addEventListener("message", (event) => {
    console.log(event.data); // Affiche : "Données reçues : Hello depuis le script principal"
});

port.start();

Cas d’utilisation courants

  • Calculs intensifs : Traitement de grandes quantités de données ou algorithmes complexes.
  • Analyse de données : Parsing de fichiers volumineux (JSON, CSV) sans ralentir l'interface utilisateur.
  • Mises à jour en temps réel : Gérer les connexions WebSocket ou les notifications.
  • Manipulation d’images ou vidéos : Traitement en arrière-plan avec des librairies comme Canvas.

Bonnes pratiques

  • Utilisez les Workers pour des tâches longues ou intensives uniquement.
  • Communiquez de manière efficace en limitant les messages envoyés entre le Worker et le thread principal.
  • Gérez les erreurs dans le Worker avec des écouteurs d'événements.
  • Nettoyez les Workers inutilisés en appelant worker.terminate() pour libérer des ressources.

Gestion des Erreurs et Debugging

En JavaScript, la gestion des erreurs et le debugging sont essentiels pour assurer la robustesse et la fiabilité des applications. Une bonne gestion des erreurs permet d'anticiper et de traiter les problèmes, tandis que le debugging aide à localiser et corriger les bugs.

Pourquoi gérer les erreurs ?

  • Prévenir les plantages : Empêche une erreur d’interrompre complètement l’exécution du programme.
  • Améliorer l’expérience utilisateur : Fournir des messages d’erreur clairs au lieu de comportements inattendus.
  • Faciliter le debugging : Identifier rapidement les causes des problèmes grâce à une gestion structurée.

Les erreurs en JavaScript

  • SyntaxError : Erreur de syntaxe, détectée lors de l’analyse du code.
  • ReferenceError : Variable ou fonction non définie.
  • TypeError : Utilisation d’une valeur avec un type inapproprié.
  • RangeError : Utilisation d'une valeur en dehors d'une plage autorisée.
  • Custom Error : Erreurs définies par le développeur.

Gestion des erreurs avec try...catch

Le bloc try...catch permet de capturer les erreurs et d’exécuter un code alternatif.

// Exemple simple avec try...catch
try {
    // Code qui peut générer une erreur
    console.log(utilisateur.nom); // ReferenceError : utilisateur n'est pas défini
} catch (erreur) {
    console.error("Une erreur est survenue :", erreur.message);
} // Continue l'exécution sans plantage

Lancer des erreurs avec throw

Vous pouvez créer vos propres erreurs personnalisées en utilisant throw pour signaler des conditions spécifiques.

// Exemple avec throw
function verifierAge(age) {
    if (age < 18) {
        throw new Error("L'âge doit être supérieur ou égal à 18.");
    }
    console.log("Âge valide :", age);
}

try {
    verifierAge(15);
} catch (erreur) {
    console.error(erreur.message); // L'âge doit être supérieur ou égal à 18.
}

Déboguer avec console

L'objet console est un outil puissant pour afficher des informations dans la console du navigateur :

  • console.log() : Affiche des informations générales.
  • console.error() : Affiche une erreur.
  • console.warn() : Affiche un avertissement.
  • console.table() : Affiche des données sous forme de tableau.
// Exemples de console
const utilisateur = { nom: "Alice", age: 30 };
console.log(utilisateur); // Affiche l'objet
console.table(utilisateur); // Affiche l'objet sous forme de tableau
console.warn("Attention : Variable non utilisée.");
console.error("Erreur critique détectée.");

Déboguer avec les outils du navigateur

Les navigateurs modernes offrent des outils de développement puissants :

  • Breakpoints : Permet de mettre en pause l'exécution du code pour analyser son état.
  • Call Stack : Affiche la pile d’appels pour retracer l’origine d’une erreur.
  • Watch Variables : Surveillez des variables spécifiques pendant l'exécution.
  • Network Tab : Vérifie les requêtes réseau pour identifier les erreurs côté serveur.

Gestion globale des erreurs

Vous pouvez capturer toutes les erreurs non gérées avec window.onerror ou window.addEventListener('error').

// Gestion globale des erreurs
window.addEventListener("error", (event) => {
    console.error(`Erreur capturée globalement : ${event.message}`);
});

Cas d’utilisation courants

  • Validation des entrées : Vérifiez les données utilisateur avant de les traiter.
  • Requêtes API : Gérez les erreurs de réseau ou de réponse.
  • Gestion des dépendances : Anticipez les erreurs causées par des modules ou scripts externes.

Bonnes pratiques

  • Utilisez try...catch uniquement pour les blocs susceptibles de générer des erreurs.
  • Écrivez des messages d'erreur clairs et descriptifs pour faciliter le debugging.
  • Gérez les erreurs spécifiques pour éviter des comportements imprévisibles.
  • Utilisez les outils de développement pour localiser et résoudre les bugs rapidement.

Service Workers & Progressive Web Apps (PWA)

Les Service Workers sont des scripts exécutés en arrière-plan par le navigateur, indépendamment des pages web. Ils sont une composante essentielle des Progressive Web Apps (PWA), offrant des fonctionnalités avancées comme le support hors ligne, les notifications push, et la mise en cache optimisée des ressources.

Pourquoi utiliser les Service Workers ?

  • Fonctionnalité hors ligne : Permet de charger des pages même sans connexion Internet.
  • Performances accrues : Mise en cache des ressources pour des temps de chargement plus rapides.
  • Notifications push : Interagir avec l'utilisateur via des notifications.
  • Fondation des PWA : Indispensables pour transformer un site web en une application progressive.

Les étapes pour utiliser un Service Worker

  1. Enregistrer le Service Worker dans votre application.
  2. Gérer l'installation et l'activation pour mettre en cache les ressources.
  3. Intercepter les requêtes réseau pour fournir des réponses en cache ou dynamiques.

Exemple pratique de Service Worker

Fichier du Service Worker (sw.js)
// sw.js - Service Worker

// Nom du cache
const CACHE_NAME = "v1";

// Ressources à mettre en cache
const ressources = [
    "/index.html",
    "/style.css",
    "/app.js",
    "/images/logo.png"
];

// Installation du Service Worker
self.addEventListener("install", (event) => {
    console.log("Service Worker : Installé");
    event.waitUntil(
        caches.open(CACHE_NAME).then((cache) => {
            console.log("Mise en cache des ressources");
            return cache.addAll(ressources);
        })
    );
});

// Activation du Service Worker
self.addEventListener("activate", (event) => {
    console.log("Service Worker : Activé");
    event.waitUntil(
        caches.keys().then((cacheNames) => {
            return Promise.all(
                cacheNames.map((cache) => {
                    if (cache !== CACHE_NAME) {
                        console.log(`Suppression de l'ancien cache : ${cache}`);
                        return caches.delete(cache);
                    }
                })
            );
        })
    );
});

// Interception des requêtes réseau
self.addEventListener("fetch", (event) => {
    console.log(`Requête interceptée : ${event.request.url}`);
    event.respondWith(
        caches.match(event.request).then((response) => {
            // Retourne la réponse en cache si disponible, sinon fait une requête réseau
            return response || fetch(event.request);
        })
    );
});
Enregistrement du Service Worker (app.js)
// app.js - Enregistrer le Service Worker

if ("serviceWorker" in navigator) {
    navigator.serviceWorker
        .register("/sw.js")
        .then((registration) => {
            console.log("Service Worker enregistré :", registration.scope);
        })
        .catch((error) => {
            console.error("Échec de l'enregistrement du Service Worker :", error);
        });
}

Progressive Web Apps (PWA)

Les PWA combinent des technologies web modernes pour offrir une expérience utilisateur proche des applications natives :

  • Installable : Ajout de l'application sur l'écran d'accueil du téléphone.
  • Fonctionnalité hors ligne : Accessible même sans connexion Internet grâce au Service Worker.
  • Performances optimisées : Chargement rapide des ressources mises en cache.
Fichier Manifest (manifest.json)

Un fichier manifest.json est requis pour transformer un site web en PWA :

{
    "name": "Ma PWA",
    "short_name": "PWA",
    "start_url": "/index.html",
    "display": "standalone",
    "background_color": "#ffffff",
    "theme_color": "#000000",
    "icons": [
        {
            "src": "/images/icon-192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "/images/icon-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}

Cas d’utilisation courants

  • Applications hors ligne : Sites web accessibles sans Internet.
  • Optimisation des performances : Mise en cache des ressources pour des temps de chargement plus rapides.
  • Notifications push : Garder les utilisateurs engagés avec des mises à jour en temps réel.

Bonnes pratiques

  • Utilisez des stratégies de mise en cache adaptées (cache first, network first, etc.).
  • Testez votre PWA avec des outils comme Lighthouse.
  • Minimisez les ressources mises en cache pour optimiser les performances.
  • Assurez-vous que le fichier manifest.json est correct et lié à votre HTML.

Syntaxe Moderne ES6+

ES6 (ECMAScript 2015) et les versions ultérieures ont introduit des fonctionnalités modernes et puissantes en JavaScript. Ces ajouts facilitent l'écriture d'un code plus propre, lisible et maintenable, tout en améliorant les performances des applications.

Pourquoi adopter la syntaxe ES6+ ?

  • Lisibilité : Syntaxe plus concise et claire.
  • Productivité : Réduit la quantité de code nécessaire pour accomplir des tâches complexes.
  • Compatibilité : La plupart des navigateurs modernes et des outils comme Babel permettent une adoption large.

Principales fonctionnalités ES6+

1. Déclaration de variables avec let et const

Avant ES6, toutes les variables étaient déclarées avec var. Désormais, let et const offrent des portées plus précises.

// Différences entre var, let, et const

// var : portée globale ou fonctionnelle
var x = 10;

// let : portée de bloc
let y = 20;

// const : valeur constante, portée de bloc
const z = 30;

// Exemple de portée
if (true) {
    let y = 50;
    console.log(y); // 50
}
console.log(y); // 20
2. Fonctions fléchées (=>)

Les fonctions fléchées introduisent une syntaxe concise pour écrire des fonctions. Elles ne modifient pas la valeur de this, ce qui est utile dans certains contextes.

// Fonction classique
function addition(a, b) {
    return a + b;
}

// Fonction fléchée
const additionFl = (a, b) => a + b;

console.log(additionFl(5, 3)); // 8
3. Littéraux de gabarits (`)

Les littéraux de gabarits permettent d'insérer facilement des variables ou des expressions dans des chaînes de caractères.

// Exemple avec littéraux de gabarits
const nom = "Alice";
const age = 30;

const message = `Bonjour, je m'appelle ${nom} et j'ai ${age} ans.`;
console.log(message);
4. Destructuration des objets et tableaux

La destructuration permet d'extraire des valeurs ou des propriétés d'objets et de tableaux.

// Destructuration des objets
const utilisateur = { nom: "Alice", age: 30 };
const { nom, age } = utilisateur;

console.log(nom); // Alice
console.log(age); // 30

// Destructuration des tableaux
const nombres = [1, 2, 3];
const [a, b] = nombres;

console.log(a); // 1
console.log(b); // 2
5. Opérateurs Spread et Rest (...)

Ces opérateurs permettent de copier, fusionner ou passer des arguments de manière flexible.

// Spread
const nombres = [1, 2, 3];
const nouveauxNombres = [...nombres, 4];

console.log(nouveauxNombres); // [1, 2, 3, 4]

// Rest
function addition(...args) {
    return args.reduce((somme, val) => somme + val);
}
console.log(addition(1, 2, 3)); // 6
6. Modules JavaScript

L'importation et l'exportation de modules facilitent l'organisation et la réutilisation du code.

// Exportation dans calcul.js
export function addition(a, b) {
    return a + b;
}

// Importation dans main.js
import { addition } from "./calcul.js";
console.log(addition(5, 3)); // 8
7. Classes

Les classes introduisent une syntaxe simplifiée pour la Programmation Orientée Objet.

// Exemple de classe
class Animal {
    constructor(nom) {
        this.nom = nom;
    }

    parler() {
        console.log(`${this.nom} fait un bruit.`);
    }
}

const chien = new Animal("Rex");
chien.parler(); // Rex fait un bruit.

Cas d’utilisation courants

  • Créer un code plus lisible et maintenable grâce à let, const, et les classes.
  • Réduire les bugs avec des modules et une structure modulaire.
  • Améliorer les performances avec des fonctions optimisées comme les littéraux de gabarits et les opérateurs spread/rest.

Tests Unitaires

Les tests unitaires consistent à vérifier individuellement chaque fonction ou composant d'un programme pour s'assurer qu'ils fonctionnent correctement. Ils permettent de détecter les bugs rapidement et d'assurer la fiabilité du code lors des modifications.

Pourquoi effectuer des tests unitaires ?

  • Détection précoce des bugs : Identifiez les problèmes avant qu'ils n'affectent l'ensemble de l'application.
  • Réduction des coûts : Corrigez les erreurs avant qu'elles ne deviennent coûteuses à résoudre.
  • Facilite la maintenance : Assurez-vous que les modifications du code n'introduisent pas de régressions.
  • Améliore la confiance : Garantit que votre code fonctionne comme prévu.

Principes des tests unitaires

  • Un test doit être indépendant des autres tests.
  • Les tests doivent être faciles à écrire, lire et maintenir.
  • Chaque test doit se concentrer sur un cas spécifique (input/output attendu).

Outils populaires pour les tests unitaires

  • Jest : Framework complet pour le test unitaire, fourni avec des fonctionnalités avancées.
  • Mocha : Framework flexible pour créer des tests personnalisés.
  • Chai : Librairie d'assertions souvent utilisée avec Mocha.
  • Vitest : Framework rapide et moderne pour les projets basés sur Vite.

Exemple de test unitaire avec Jest

Fichier à tester (calcul.js)
// Fonction à tester
export function addition(a, b) {
    return a + b;
}

export function division(a, b) {
    if (b === 0) {
        throw new Error("Division par zéro interdite");
    }
    return a / b;
}
Fichier de test (calcul.test.js)
// Importation des fonctions à tester
import { addition, division } from "./calcul.js";

// Tests pour la fonction addition
test("Addition de deux nombres positifs", () => {
    expect(addition(2, 3)).toBe(5);
});

test("Addition avec zéro", () => {
    expect(addition(0, 3)).toBe(3);
});

// Tests pour la fonction division
test("Division de deux nombres positifs", () => {
    expect(division(10, 2)).toBe(5);
});

test("Division par zéro génère une erreur", () => {
    expect(() => division(10, 0)).toThrow("Division par zéro interdite");
});

Commandes pour exécuter les tests

  • npm install jest --save-dev : Installe Jest dans votre projet.
  • npx jest : Lance tous les tests.
  • npx jest --watch : Exécute les tests automatiquement à chaque modification de fichier.

Cas d’utilisation courants

  • Validation de logique métier : Tester les calculs, les conversions, ou toute logique clé.
  • Gestion des erreurs : S'assurer que les exceptions sont correctement levées et gérées.
  • Régressions : Vérifier que les nouvelles fonctionnalités n’introduisent pas de bugs dans le code existant.

Bonnes pratiques

  • Écrivez des tests simples et ciblés pour chaque cas d'utilisation.
  • Assurez-vous que les noms des tests décrivent clairement leur objectif.
  • Automatisez vos tests pour exécuter régulièrement votre suite.
  • Évitez les dépendances externes dans vos tests unitaires.
  • Incluez des tests pour les cas normaux, limites et erreurs.