1432 lines
58 KiB
HTML
1432 lines
58 KiB
HTML
<!DOCTYPE html>
|
||
<!--
|
||
=====================================================================
|
||
index.html — la STRUCTURE de la page
|
||
---------------------------------------------------------------------
|
||
Une page web, c'est (presque toujours) TROIS langages qui coopèrent :
|
||
|
||
HTML → le CONTENU et sa structure (ce fichier) "le squelette"
|
||
CSS → l'APPARENCE (style.css) "la peau"
|
||
JS → le COMPORTEMENT (script.js) "les muscles"
|
||
|
||
Le HTML est fait de BALISES : <nom attribut="valeur"> contenu </nom>
|
||
Certaines balises n'ont pas de fermeture : <meta>, <link>, <img>…
|
||
|
||
Ceci est un COMMENTAIRE HTML : le navigateur l'ignore complètement.
|
||
=====================================================================
|
||
-->
|
||
<html lang="fr"> <!-- lang="fr" : aide les lecteurs d'écran et la traduction -->
|
||
<head>
|
||
<!-- Le <head> contient les infos SUR la page (invisibles à l'écran) -->
|
||
|
||
<!-- Encodage des caractères : indispensable pour les accents é, à, ç… -->
|
||
<meta charset="UTF-8">
|
||
|
||
<!-- Indispensable sur mobile : la page s'adapte à la largeur de l'écran -->
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<!-- Le titre affiché dans l'onglet du navigateur -->
|
||
<title>Intro JavaScript</title>
|
||
|
||
<!-- On relie la feuille de style CSS -->
|
||
<link rel="stylesheet" href="style.css">
|
||
|
||
<!--
|
||
On relie le script JS. L'attribut "defer" signifie :
|
||
"télécharge-le tout de suite, mais attends que le HTML soit
|
||
entièrement lu avant de l'exécuter". Sans ça, le script pourrait
|
||
chercher des éléments qui n'existent pas encore.
|
||
-->
|
||
<script src="script.js" defer></script>
|
||
</head>
|
||
|
||
<body>
|
||
<!-- Le <body> contient tout ce qui est VISIBLE -->
|
||
|
||
<div class="mise-en-page">
|
||
|
||
<!-- ============================ MENU ============================ -->
|
||
<!-- <nav> = zone de navigation. Les liens href="#xxx" mènent à l'élément id="xxx" -->
|
||
<nav class="sommaire" aria-label="Sommaire">
|
||
<div class="logo"><span>JS</span> Intro au code</div>
|
||
<ol>
|
||
<li><a href="#ch0">Coder, c'est quoi ?</a></li>
|
||
<li><a href="#ch1">Console & commentaires</a></li>
|
||
<li><a href="#ch2">Variables</a></li>
|
||
<li><a href="#ch3">Types de données</a></li>
|
||
<li><a href="#ch4">Opérateurs</a></li>
|
||
<li><a href="#ch5">Conditions</a></li>
|
||
<li><a href="#ch6">Boucles</a></li>
|
||
<li><a href="#ch7">Fonctions</a></li>
|
||
<li><a href="#ch8">Tableaux</a></li>
|
||
<li><a href="#ch9">Objets</a></li>
|
||
<li><a href="#ch10">Le DOM</a></li>
|
||
<li><a href="#ch11">Événements</a></li>
|
||
<li><a href="#ch12">Asynchrone</a></li>
|
||
<li><a href="#ch13">Classes</a></li>
|
||
<li><a href="#ch14">Mini-projet</a></li>
|
||
<li><a href="#ch15">Et après ?</a></li>
|
||
</ol>
|
||
<button id="bouton-theme" type="button">◐ Clair / sombre</button>
|
||
</nav>
|
||
|
||
<!-- ========================== CONTENU ========================== -->
|
||
<main>
|
||
|
||
<header class="intro">
|
||
<h1>Apprendre à coder avec <mark>JavaScript</mark></h1>
|
||
<p class="chapeau">
|
||
On part de zéro, on va loin. Chaque exemple est <strong>modifiable</strong> et
|
||
<strong>exécutable</strong> directement dans la page : lis, change, casse, recommence.
|
||
</p>
|
||
<div class="encadre astuce">
|
||
<strong>Comment utiliser cette page</strong>
|
||
Dans chaque bloc noir, modifie le code puis clique sur <code>▶ Exécuter</code>
|
||
(ou <code>Ctrl + Entrée</code>). Le bouton <code>↺</code> remet l'exemple d'origine.
|
||
Tout ce qui suit <code>//</code> est un commentaire : lis-les, ils expliquent tout.
|
||
</div>
|
||
</header>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch0">
|
||
<h2><span class="num">00</span>Coder, c'est quoi ?</h2>
|
||
|
||
<p>
|
||
Un ordinateur est extrêmement rapide mais complètement <strong>bête</strong> :
|
||
il fait exactement ce qu'on lui dit, ligne par ligne, sans jamais deviner ce qu'on
|
||
« voulait dire ». <strong>Coder</strong>, c'est écrire ces instructions dans
|
||
un langage précis qu'il comprend.
|
||
</p>
|
||
|
||
<p>
|
||
<strong>JavaScript</strong> (JS) est le langage des navigateurs web. Toutes les pages
|
||
interactives que tu utilises (menus, formulaires, jeux, cartes…) en contiennent.
|
||
Il tourne aussi sur des serveurs (Node.js), dans des applis, des objets connectés…
|
||
</p>
|
||
|
||
<h3>Les 3 couches d'une page web</h3>
|
||
<pre class="schema">
|
||
┌────────────┐ ┌────────────┐ ┌────────────────┐
|
||
│ HTML │ │ CSS │ │ JavaScript │
|
||
│ le contenu │ + │ l'apparence│ + │ le comportement│
|
||
│ "un titre" │ │ "en rouge" │ │ "si on clique, │
|
||
│ │ │ │ │ il grossit" │
|
||
└────────────┘ └────────────┘ └────────────────┘
|
||
index.html style.css script.js
|
||
</pre>
|
||
|
||
<h3>Un programme = des instructions, dans l'ordre</h3>
|
||
<p>
|
||
Le code se lit <strong>de haut en bas</strong>. Chaque ligne est une instruction,
|
||
généralement terminée par un point-virgule <code>;</code>.
|
||
Essaie : clique sur Exécuter.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>premier-programme.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// Ceci est un commentaire : l'ordinateur l'ignore.
|
||
// Il sert aux HUMAINS qui lisent le code.
|
||
|
||
console.log("Bonjour !"); // 1re instruction
|
||
console.log("Je suis un programme"); // 2e instruction
|
||
console.log(2 + 3); // 3e : JS sait calculer
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="encadre">
|
||
<strong>La console du navigateur</strong>
|
||
Appuie sur <code>F12</code> (ou clic droit → Inspecter) puis onglet « Console ».
|
||
C'est l'outil n°1 du développeur : on y voit les messages et les erreurs.
|
||
Tu peux même y taper du JavaScript directement.
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch1">
|
||
<h2><span class="num">01</span>La console & les commentaires</h2>
|
||
|
||
<p>
|
||
<code>console.log(...)</code> affiche ce qu'on met entre les parenthèses.
|
||
C'est ton meilleur ami pour <strong>comprendre ce qui se passe</strong> dans ton code :
|
||
quand quelque chose ne marche pas, on affiche des valeurs pour vérifier.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>console.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// Commentaire sur une ligne : tout ce qui suit // est ignoré
|
||
|
||
/*
|
||
Commentaire sur
|
||
plusieurs lignes :
|
||
tout ce qui est entre la barre-étoile d'ouverture
|
||
et l'étoile-barre de fermeture est ignoré
|
||
*/
|
||
|
||
console.log("Du texte"); // un texte s'écrit entre guillemets
|
||
console.log(42); // un nombre s'écrit sans guillemets
|
||
console.log("A", "B", 3); // plusieurs valeurs séparées par des virgules
|
||
|
||
console.warn("Un avertissement"); // variantes : warn, error, info
|
||
console.error("Une erreur (pour de faux)");
|
||
console.info("Une information");
|
||
|
||
// À toi : affiche ton prénom sur la ligne suivante
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="encadre astuce">
|
||
<strong>Bonne pratique</strong>
|
||
Un bon commentaire explique <em>pourquoi</em> on fait quelque chose, pas seulement
|
||
<em>quoi</em>. Le code dit déjà « quoi » ; le commentaire raconte l'intention.
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch2">
|
||
<h2><span class="num">02</span>Les variables : des boîtes avec une étiquette</h2>
|
||
|
||
<p>
|
||
Une <strong>variable</strong> est une boîte qui porte un nom et contient une valeur.
|
||
On la crée (on dit <em>déclare</em>) une fois, puis on l'utilise par son nom.
|
||
</p>
|
||
|
||
<pre class="schema">
|
||
let age = 20;
|
||
|
||
┌─────────┐
|
||
│ 20 │ ← la valeur (ce qu'il y a dedans)
|
||
└─────────┘
|
||
age ← l'étiquette (le nom de la variable)
|
||
</pre>
|
||
|
||
<table>
|
||
<tr><th>Mot-clé</th><th>Peut-on changer la valeur ?</th><th>Quand l'utiliser</th></tr>
|
||
<tr><td><code>const</code></td><td>Non</td><td>Par défaut, tout le temps</td></tr>
|
||
<tr><td><code>let</code></td><td>Oui</td><td>Quand la valeur doit évoluer (compteur, score…)</td></tr>
|
||
<tr><td><code>var</code></td><td>Oui</td><td>Jamais : ancienne syntaxe, comportements piégeux</td></tr>
|
||
</table>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>variables.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// "let" crée une variable dont la valeur peut changer
|
||
let score = 0;
|
||
console.log("Score de départ :", score);
|
||
|
||
score = 10; // on REMPLACE la valeur (pas de "let" cette fois !)
|
||
console.log("Score après :", score);
|
||
|
||
score = score + 5; // on prend l'ancienne valeur, on ajoute 5, on range
|
||
console.log("Score + 5 :", score);
|
||
|
||
// "const" crée une constante : sa valeur ne changera JAMAIS
|
||
const prenom = "Ada";
|
||
console.log("Bonjour", prenom);
|
||
|
||
// Décommente la ligne suivante (enlève les //) et exécute : erreur !
|
||
// prenom = "Alan";
|
||
|
||
// Règles de nommage :
|
||
// - pas d'espace, pas de tiret, ne commence pas par un chiffre
|
||
// - sensible à la casse : age ≠ Age
|
||
// - convention "camelCase" : nombreDeVies, prixTotal
|
||
const nombreDeVies = 3;
|
||
console.log(nombreDeVies);
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>La portée (scope) : où une variable existe</h3>
|
||
<p>
|
||
Une variable déclarée avec <code>let</code> ou <code>const</code> n'existe que
|
||
<strong>dans le bloc <code>{ }</code></strong> où elle est créée.
|
||
En dehors, elle est invisible.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>portee.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const dehors = "je suis visible partout dans ce code";
|
||
|
||
{
|
||
// Ceci est un bloc. Ce qui est créé ici reste ici.
|
||
const dedans = "je n'existe que dans ce bloc";
|
||
console.log(dehors); // ✔ on voit ce qui est à l'extérieur
|
||
console.log(dedans); // ✔
|
||
}
|
||
|
||
console.log(dehors); // ✔
|
||
console.log(dedans); // ✖ ReferenceError : "dedans" n'existe pas ici
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch3">
|
||
<h2><span class="num">03</span>Les types de données</h2>
|
||
|
||
<p>Toute valeur a un <strong>type</strong>. Les principaux :</p>
|
||
|
||
<table>
|
||
<tr><th>Type</th><th>Exemple</th><th>C'est quoi</th></tr>
|
||
<tr><td><code>string</code></td><td><code>"bonjour"</code></td><td>Du texte (chaîne de caractères)</td></tr>
|
||
<tr><td><code>number</code></td><td><code>42</code>, <code>3.14</code></td><td>Un nombre (entier ou à virgule, avec un point)</td></tr>
|
||
<tr><td><code>boolean</code></td><td><code>true</code>, <code>false</code></td><td>Vrai ou faux</td></tr>
|
||
<tr><td><code>undefined</code></td><td><code>undefined</code></td><td>« Pas encore de valeur »</td></tr>
|
||
<tr><td><code>null</code></td><td><code>null</code></td><td>« Vide, volontairement »</td></tr>
|
||
<tr><td><code>object</code></td><td><code>{ }</code>, <code>[ ]</code></td><td>Une structure qui regroupe des valeurs (chap. 8 et 9)</td></tr>
|
||
</table>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>types.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// typeof permet de connaître le type d'une valeur
|
||
console.log(typeof "salut"); // "string"
|
||
console.log(typeof 12); // "number"
|
||
console.log(typeof true); // "boolean"
|
||
console.log(typeof undefined); // "undefined"
|
||
|
||
let pasEncore; // déclarée mais jamais remplie
|
||
console.log(pasEncore); // undefined
|
||
|
||
// --- Les textes (strings) ---
|
||
// 3 sortes de guillemets : "doubles", 'simples', `backticks`
|
||
const ville = "Le Havre";
|
||
const phrase1 = "J'habite au " + ville; // + colle les textes (concaténation)
|
||
const phrase2 = `J'habite au ${ville}`; // gabarit : ${...} insère une valeur
|
||
console.log(phrase1);
|
||
console.log(phrase2);
|
||
console.log(`2 + 2 = ${2 + 2}`); // on peut même calculer dedans
|
||
|
||
// Les strings ont des "méthodes" : des actions qu'on leur demande
|
||
console.log(ville.length); // nombre de caractères
|
||
console.log(ville.toUpperCase()); // en majuscules
|
||
console.log(ville.includes("Havre"));// contient "Havre" ? → true
|
||
console.log(ville[0]); // 1er caractère (on compte à partir de 0 !)
|
||
|
||
// --- Conversion de types ---
|
||
console.log("5" + 3); // "53" ← piège : + avec un texte = collage !
|
||
console.log("5" * 3); // 15 ← * force la conversion en nombre
|
||
console.log(Number("5") + 3); // 8 ← on convertit explicitement : plus clair
|
||
console.log(String(42)); // "42"
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="encadre attention">
|
||
<strong>Piège classique</strong>
|
||
Ce qu'on récupère d'un champ de formulaire est <em>toujours</em> du texte,
|
||
même si l'utilisateur tape un nombre. Pense à le convertir avec <code>Number()</code>.
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch4">
|
||
<h2><span class="num">04</span>Les opérateurs</h2>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>operateurs.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// --- Arithmétique ---
|
||
console.log(7 + 2); // 9 addition
|
||
console.log(7 - 2); // 5 soustraction
|
||
console.log(7 * 2); // 14 multiplication
|
||
console.log(7 / 2); // 3.5 division
|
||
console.log(7 % 2); // 1 MODULO : le reste de la division (7 = 3×2 + 1)
|
||
console.log(2 ** 3); // 8 puissance (2×2×2)
|
||
|
||
// Le modulo sert souvent à savoir si un nombre est pair :
|
||
console.log(10 % 2 === 0); // true → 10 est pair
|
||
|
||
// --- Raccourcis d'affectation ---
|
||
let n = 10;
|
||
n += 5; // pareil que n = n + 5 → 15
|
||
n -= 3; // n = n - 3 → 12
|
||
n *= 2; // n = n * 2 → 24
|
||
n++; // n = n + 1 → 25
|
||
console.log(n);
|
||
|
||
// --- Comparaison : le résultat est TOUJOURS un booléen ---
|
||
console.log(5 > 3); // true
|
||
console.log(5 <= 3); // false
|
||
console.log(5 === 5); // true strictement égal (même valeur ET même type)
|
||
console.log(5 !== 4); // true différent
|
||
|
||
// ⚠ == (double égal) convertit les types avant de comparer : piégeux !
|
||
console.log(5 == "5"); // true 😬
|
||
console.log(5 === "5"); // false ✔ utilise TOUJOURS ===
|
||
|
||
// --- Logique : combiner des conditions ---
|
||
const aFaim = true;
|
||
const aDeLArgent = false;
|
||
console.log(aFaim && aDeLArgent); // ET : vrai seulement si les DEUX sont vrais → false
|
||
console.log(aFaim || aDeLArgent); // OU : vrai si AU MOINS UN est vrai → true
|
||
console.log(!aFaim); // NON : inverse → false
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="exercice">
|
||
<strong>Exercice</strong> — Une pizza coûte 12 €, on en commande 3, et on a un bon de
|
||
réduction de 20 %. Calcule et affiche le prix final avec des variables bien nommées.
|
||
<details>
|
||
<summary>Voir une solution</summary>
|
||
<div class="bac">
|
||
<div class="barre"><span>solution.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const prixPizza = 12;
|
||
const quantite = 3;
|
||
const reduction = 0.20; // 20 % = 20 / 100
|
||
|
||
const total = prixPizza * quantite; // 36
|
||
const prixFinal = total * (1 - reduction); // on paie 80 % du total
|
||
|
||
console.log(`Prix final : ${prixFinal} €`);
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch5">
|
||
<h2><span class="num">05</span>Les conditions : prendre des décisions</h2>
|
||
|
||
<p>
|
||
Un programme doit souvent choisir : <em>si</em> quelque chose est vrai, faire ceci,
|
||
<em>sinon</em> faire cela.
|
||
</p>
|
||
|
||
<pre class="schema">
|
||
┌──────────────┐
|
||
│ age >= 18 ? │
|
||
└──────┬───────┘
|
||
oui ┌────┴────┐ non
|
||
▼ ▼
|
||
"majeur" "mineur"
|
||
</pre>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>conditions.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const age = 16; // ← change cette valeur et ré-exécute
|
||
|
||
// if (condition) { ... } else { ... }
|
||
if (age >= 18) {
|
||
// ce bloc s'exécute seulement si la condition est vraie
|
||
console.log("Tu es majeur·e");
|
||
} else {
|
||
// sinon, c'est celui-ci
|
||
console.log("Tu es mineur·e");
|
||
}
|
||
|
||
// Plusieurs cas : else if
|
||
const note = 14;
|
||
if (note >= 16) {
|
||
console.log("Très bien");
|
||
} else if (note >= 12) {
|
||
console.log("Bien"); // ← on s'arrête au PREMIER cas vrai
|
||
} else if (note >= 10) {
|
||
console.log("Passable");
|
||
} else {
|
||
console.log("Insuffisant");
|
||
}
|
||
|
||
// L'opérateur ternaire : un if/else compact pour choisir une VALEUR
|
||
// condition ? valeurSiVrai : valeurSiFaux
|
||
const statut = age >= 18 ? "adulte" : "enfant";
|
||
console.log(statut);
|
||
|
||
// Valeurs "truthy" / "falsy" : dans un if, toute valeur devient vrai ou faux.
|
||
// Sont FAUSSES : false, 0, "" (texte vide), null, undefined, NaN
|
||
// Tout le reste est VRAI.
|
||
const pseudo = "";
|
||
if (pseudo) {
|
||
console.log("Bienvenue " + pseudo);
|
||
} else {
|
||
console.log("Tu n'as pas de pseudo !");
|
||
}
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>switch : comparer une valeur à plusieurs cas précis</h3>
|
||
<div class="bac">
|
||
<div class="barre"><span>switch.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const jour = "samedi";
|
||
|
||
switch (jour) {
|
||
case "samedi":
|
||
case "dimanche": // deux cas qui partagent le même code
|
||
console.log("Week-end ! 🎉");
|
||
break; // ⚠ "break" stoppe le switch, sinon on continue dans le cas suivant
|
||
case "mercredi":
|
||
console.log("Club info !");
|
||
break;
|
||
default: // si aucun cas ne correspond
|
||
console.log("Jour de cours");
|
||
}
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch6">
|
||
<h2><span class="num">06</span>Les boucles : répéter sans se répéter</h2>
|
||
|
||
<p>
|
||
Afficher les nombres de 1 à 1000 ? On ne va pas écrire 1000 lignes.
|
||
Une <strong>boucle</strong> répète un bloc de code tant qu'une condition est vraie.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>boucles.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// --- La boucle for : quand on sait combien de fois répéter ---
|
||
// for (départ ; condition pour continuer ; étape après chaque tour)
|
||
for (let i = 1; i <= 5; i++) {
|
||
console.log("Tour n°" + i);
|
||
}
|
||
// Déroulé : i=1 → affiche → i++ (i=2) → 2<=5 ? oui → affiche → … → i=6 → 6<=5 ? non → fin
|
||
|
||
// --- La boucle while : tant que la condition est vraie ---
|
||
let pieces = 3;
|
||
while (pieces > 0) {
|
||
console.log(`Il reste ${pieces} pièce(s)`);
|
||
pieces--; // ⚠ sans cette ligne : BOUCLE INFINIE, la page gèle !
|
||
}
|
||
console.log("Plus de pièces.");
|
||
|
||
// --- break et continue ---
|
||
for (let i = 1; i <= 10; i++) {
|
||
if (i % 2 === 0) continue; // continue : saute au tour suivant (on ignore les pairs)
|
||
if (i > 7) break; // break : sort complètement de la boucle
|
||
console.log("impair :", i);
|
||
}
|
||
|
||
// --- Boucles imbriquées : une table de multiplication ---
|
||
for (let ligne = 1; ligne <= 3; ligne++) {
|
||
let texte = "";
|
||
for (let col = 1; col <= 5; col++) {
|
||
texte += (ligne * col) + "\t"; // \t = tabulation
|
||
}
|
||
console.log(texte);
|
||
}
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="exercice">
|
||
<strong>Exercice : FizzBuzz</strong> (un classique des entretiens d'embauche !) —
|
||
Affiche les nombres de 1 à 20, mais : remplace les multiples de 3 par « Fizz »,
|
||
ceux de 5 par « Buzz », et ceux de 3 <em>et</em> 5 par « FizzBuzz ».
|
||
<details>
|
||
<summary>Un indice</summary>
|
||
<p>Utilise le modulo <code>%</code>. Et teste d'abord le cas « 3 ET 5 »… pourquoi ?</p>
|
||
</details>
|
||
<details>
|
||
<summary>Voir une solution</summary>
|
||
<div class="bac">
|
||
<div class="barre"><span>fizzbuzz.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
for (let i = 1; i <= 20; i++) {
|
||
// On teste le cas le plus précis en PREMIER,
|
||
// sinon 15 serait attrapé par "multiple de 3" et s'arrêterait là.
|
||
if (i % 3 === 0 && i % 5 === 0) {
|
||
console.log("FizzBuzz");
|
||
} else if (i % 3 === 0) {
|
||
console.log("Fizz");
|
||
} else if (i % 5 === 0) {
|
||
console.log("Buzz");
|
||
} else {
|
||
console.log(i);
|
||
}
|
||
}
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch7">
|
||
<h2><span class="num">07</span>Les fonctions : des recettes réutilisables</h2>
|
||
|
||
<p>
|
||
Une <strong>fonction</strong> est un morceau de code auquel on donne un nom, pour
|
||
pouvoir le lancer (on dit <em>appeler</em>) autant de fois qu'on veut.
|
||
Elle peut recevoir des <strong>paramètres</strong> (les ingrédients) et
|
||
<strong>renvoyer</strong> un résultat (le plat).
|
||
</p>
|
||
|
||
<pre class="schema">
|
||
paramètres fonction valeur renvoyée
|
||
(3, 4) ───▶ ┌──────────────┐ ───▶ 7
|
||
│ additionner │
|
||
└──────────────┘
|
||
</pre>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>fonctions.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// 1. DÉCLARER la fonction (on écrit la recette, rien ne s'exécute encore)
|
||
function direBonjour(prenom) { // "prenom" est un PARAMÈTRE
|
||
console.log(`Bonjour ${prenom} !`);
|
||
}
|
||
|
||
// 2. APPELER la fonction (on cuisine) : nom + parenthèses
|
||
direBonjour("Ada"); // "Ada" est un ARGUMENT
|
||
direBonjour("Alan");
|
||
|
||
// --- return : renvoyer un résultat ---
|
||
function additionner(a, b) {
|
||
return a + b; // return renvoie la valeur ET arrête la fonction
|
||
console.log("jamais affiché"); // code mort : après un return, plus rien ne s'exécute
|
||
}
|
||
const resultat = additionner(3, 4); // on récupère ce qui est renvoyé
|
||
console.log(resultat); // 7
|
||
console.log(additionner(10, additionner(1, 2))); // on peut imbriquer : 13
|
||
|
||
// Sans return, une fonction renvoie undefined
|
||
console.log(direBonjour("Grace")); // affiche le bonjour, PUIS undefined
|
||
|
||
// --- Paramètre par défaut ---
|
||
function saluer(nom = "inconnu·e") {
|
||
return "Salut " + nom;
|
||
}
|
||
console.log(saluer()); // "Salut inconnu·e"
|
||
console.log(saluer("Linus"));
|
||
|
||
// --- Fonction fléchée (arrow function) : syntaxe courte, très utilisée ---
|
||
const carre = (x) => x * x; // si une seule expression : return implicite
|
||
const auCube = x => { // avec des accolades : return obligatoire
|
||
const c = x * x * x;
|
||
return c;
|
||
};
|
||
console.log(carre(5), auCube(3));
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>Les fonctions sont des valeurs</h3>
|
||
<p>
|
||
En JS, une fonction peut être rangée dans une variable, ou <strong>passée en
|
||
argument</strong> à une autre fonction. Une fonction passée ainsi s'appelle un
|
||
<em>callback</em> (« rappel »). C'est une idée centrale en JavaScript.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>callbacks.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// Cette fonction reçoit une AUTRE fonction en paramètre ("action")
|
||
function repeter(fois, action) {
|
||
for (let i = 0; i < fois; i++) {
|
||
action(i); // on appelle la fonction reçue
|
||
}
|
||
}
|
||
|
||
repeter(3, (numero) => console.log("Hip hip hip… hourra !", numero));
|
||
|
||
// Une fonction peut aussi FABRIQUER et renvoyer une fonction
|
||
function creerMultiplicateur(facteur) {
|
||
// La fonction renvoyée "se souvient" de facteur : c'est une CLOSURE (fermeture)
|
||
return (nombre) => nombre * facteur;
|
||
}
|
||
const doubler = creerMultiplicateur(2);
|
||
const tripler = creerMultiplicateur(3);
|
||
console.log(doubler(10), tripler(10)); // 20 30
|
||
|
||
// --- Récursivité : une fonction qui s'appelle elle-même ---
|
||
// factorielle(4) = 4 × 3 × 2 × 1
|
||
function factorielle(n) {
|
||
if (n <= 1) return 1; // le CAS DE BASE : indispensable pour s'arrêter !
|
||
return n * factorielle(n - 1); // on réduit le problème à chaque appel
|
||
}
|
||
console.log(factorielle(5)); // 120
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="exercice">
|
||
<strong>Exercice</strong> — Écris une fonction <code>estPair(n)</code> qui renvoie
|
||
<code>true</code> ou <code>false</code>, puis une fonction <code>maximum(a, b)</code>
|
||
qui renvoie le plus grand des deux nombres.
|
||
<details>
|
||
<summary>Voir une solution</summary>
|
||
<div class="bac">
|
||
<div class="barre"><span>solution.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// Une comparaison donne déjà un booléen : pas besoin de if !
|
||
const estPair = (n) => n % 2 === 0;
|
||
|
||
function maximum(a, b) {
|
||
return a > b ? a : b; // ternaire
|
||
}
|
||
|
||
console.log(estPair(4), estPair(7)); // true false
|
||
console.log(maximum(3, 9)); // 9
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch8">
|
||
<h2><span class="num">08</span>Les tableaux : des listes de valeurs</h2>
|
||
|
||
<p>
|
||
Un <strong>tableau</strong> (<em>array</em>) range plusieurs valeurs dans l'ordre.
|
||
Chaque case a un numéro, l'<strong>indice</strong>, qui commence à <strong>0</strong>.
|
||
</p>
|
||
|
||
<pre class="schema">
|
||
const fruits = ["pomme", "kiwi", "poire"];
|
||
|
||
indice : 0 1 2
|
||
┌───────┬───────┬───────┐
|
||
│ pomme │ kiwi │ poire │ fruits.length → 3
|
||
└───────┴───────┴───────┘
|
||
</pre>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>tableaux.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const fruits = ["pomme", "kiwi", "poire"];
|
||
|
||
console.log(fruits[0]); // "pomme" (1er élément)
|
||
console.log(fruits.length); // 3
|
||
console.log(fruits[fruits.length - 1]); // le DERNIER élément
|
||
console.log(fruits[10]); // undefined : la case n'existe pas
|
||
|
||
// Modifier
|
||
fruits[1] = "mangue"; // remplace "kiwi"
|
||
fruits.push("banane"); // ajoute à la FIN
|
||
fruits.unshift("fraise"); // ajoute au DÉBUT
|
||
console.log(fruits);
|
||
|
||
const dernier = fruits.pop(); // retire (et renvoie) le dernier
|
||
console.log("retiré :", dernier, "→", fruits);
|
||
|
||
// Rechercher
|
||
console.log(fruits.includes("poire")); // true
|
||
console.log(fruits.indexOf("poire")); // sa position (-1 si absent)
|
||
|
||
// Parcourir : for...of donne directement chaque élément
|
||
for (const fruit of fruits) {
|
||
console.log("J'aime la " + fruit);
|
||
}
|
||
|
||
// 💡 Pourquoi "const" alors qu'on modifie le tableau ?
|
||
// const empêche de remplacer la BOÎTE (fruits = autre chose),
|
||
// mais on peut changer son CONTENU.
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>Les super-pouvoirs : map, filter, reduce…</h3>
|
||
<p>
|
||
Ces méthodes prennent une <strong>fonction</strong> (un callback, vu au chapitre 7)
|
||
et l'appliquent à chaque élément. Elles ne modifient pas le tableau d'origine :
|
||
elles en <strong>renvoient un nouveau</strong>. C'est le style « moderne » de JS.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>map-filter-reduce.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const notes = [12, 8, 15, 19, 6, 11];
|
||
|
||
// forEach : fait quelque chose pour chaque élément (ne renvoie rien)
|
||
notes.forEach((note, indice) => console.log(`Élève ${indice} : ${note}`));
|
||
|
||
// map : TRANSFORME chaque élément → nouveau tableau de même taille
|
||
const notesSur100 = notes.map(note => note * 5);
|
||
console.log("sur 100 :", notesSur100);
|
||
|
||
// filter : GARDE seulement les éléments pour lesquels la fonction renvoie true
|
||
const reussites = notes.filter(note => note >= 10);
|
||
console.log("≥ 10 :", reussites);
|
||
|
||
// find : renvoie le PREMIER élément qui correspond
|
||
console.log("1re note > 14 :", notes.find(note => note > 14));
|
||
|
||
// reduce : RÉDUIT le tableau à une seule valeur (ici : la somme)
|
||
// acc = l'accumulateur (le résultat en cours), 0 = sa valeur de départ
|
||
const somme = notes.reduce((acc, note) => acc + note, 0);
|
||
console.log("somme :", somme, "moyenne :", (somme / notes.length).toFixed(2));
|
||
|
||
// sort : trie (⚠ modifie le tableau ! on copie d'abord avec [...notes])
|
||
const triees = [...notes].sort((a, b) => a - b);
|
||
console.log("triées :", triees);
|
||
|
||
// On peut ENCHAÎNER les méthodes :
|
||
const resultat = notes
|
||
.filter(n => n >= 10) // on garde les réussites
|
||
.map(n => n + 1) // on ajoute un point bonus
|
||
.join(" / "); // on colle en un seul texte
|
||
console.log(resultat);
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch9">
|
||
<h2><span class="num">09</span>Les objets : décrire une chose</h2>
|
||
|
||
<p>
|
||
Un tableau range des valeurs <em>par position</em>. Un <strong>objet</strong> les
|
||
range <em>par nom</em> : des paires <code>clé: valeur</code> qu'on appelle
|
||
<strong>propriétés</strong>. Idéal pour décrire un utilisateur, un produit, un personnage…
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>objets.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const perso = {
|
||
nom: "Link", // clé "nom", valeur "Link"
|
||
vie: 3,
|
||
inventaire: ["épée", "bouclier"], // une valeur peut être un tableau…
|
||
position: { x: 10, y: 4 }, // …ou un autre objet
|
||
// Une fonction dans un objet s'appelle une MÉTHODE
|
||
sePresenter() {
|
||
// "this" désigne l'objet lui-même
|
||
return `Je suis ${this.nom}, j'ai ${this.vie} cœurs.`;
|
||
},
|
||
};
|
||
|
||
// Lire une propriété : notation pointée
|
||
console.log(perso.nom);
|
||
console.log(perso.position.x);
|
||
console.log(perso.inventaire[0]);
|
||
|
||
// Notation crochets : utile quand le nom de la clé est dans une variable
|
||
const cle = "vie";
|
||
console.log(perso[cle]);
|
||
|
||
// Modifier / ajouter / supprimer
|
||
perso.vie -= 1; // modifie
|
||
perso.niveau = 1; // ajoute une nouvelle propriété
|
||
delete perso.position; // supprime
|
||
console.log(perso.sePresenter());
|
||
console.log(perso);
|
||
|
||
// Parcourir les clés
|
||
for (const k in perso) {
|
||
console.log("clé :", k);
|
||
}
|
||
console.log(Object.keys(perso)); // tableau des clés
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>Syntaxes modernes très courantes</h3>
|
||
<div class="bac">
|
||
<div class="barre"><span>moderne.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const film = { titre: "Akira", annee: 1988, realisateur: "Ōtomo" };
|
||
|
||
// DÉSTRUCTURATION : extraire des propriétés dans des variables
|
||
const { titre, annee } = film;
|
||
console.log(titre, annee);
|
||
|
||
// Fonctionne aussi avec les tableaux (par position)
|
||
const [premier, second] = ["or", "argent", "bronze"];
|
||
console.log(premier, second);
|
||
|
||
// SPREAD (...) : "étaler" le contenu pour copier / fusionner
|
||
const filmComplet = { ...film, genre: "animation" }; // copie + ajout
|
||
console.log(filmComplet);
|
||
const tous = [...[1, 2], ...[3, 4]];
|
||
console.log(tous);
|
||
|
||
// CHAÎNAGE OPTIONNEL ?. : évite l'erreur si une propriété n'existe pas
|
||
console.log(film.suite?.titre); // undefined (au lieu d'une TypeError)
|
||
|
||
// Un tableau d'objets : LA structure de données la plus courante sur le web
|
||
const eleves = [
|
||
{ nom: "Inès", age: 19 },
|
||
{ nom: "Tom", age: 22 },
|
||
{ nom: "Léa", age: 20 },
|
||
];
|
||
const noms = eleves.filter(e => e.age >= 20).map(e => e.nom);
|
||
console.log(noms);
|
||
|
||
// JSON : le format texte pour échanger des données (avec un serveur, un fichier…)
|
||
const texteJSON = JSON.stringify(eleves[0]); // objet → texte
|
||
console.log(texteJSON, typeof texteJSON);
|
||
const objetRelu = JSON.parse('{"nom":"Sam","age":21}'); // texte → objet
|
||
console.log(objetRelu.nom);
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<div class="encadre attention">
|
||
<strong>Copie ou référence ?</strong>
|
||
<code>const b = a;</code> ne copie <em>pas</em> un objet ou un tableau : <code>a</code>
|
||
et <code>b</code> désignent alors <em>le même</em> objet. Modifier l'un modifie l'autre.
|
||
Pour copier : <code>const b = { ...a };</code> ou <code>[...a]</code>.
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch10">
|
||
<h2><span class="num">10</span>Le DOM : piloter la page avec JS</h2>
|
||
|
||
<p>
|
||
Quand le navigateur lit le HTML, il construit en mémoire un <strong>arbre
|
||
d'objets</strong> : le <strong>DOM</strong> (<em>Document Object Model</em>).
|
||
JavaScript peut lire et modifier cet arbre… et la page change instantanément à l'écran.
|
||
</p>
|
||
|
||
<pre class="schema">
|
||
document
|
||
└── html
|
||
├── head
|
||
│ └── title
|
||
└── body
|
||
├── h1 ← document.querySelector("h1")
|
||
└── div.carte ← document.querySelector(".carte")
|
||
└── p
|
||
</pre>
|
||
|
||
<div class="encadre">
|
||
<strong>Note sur les exemples</strong>
|
||
Dans une vraie page, on cherche les éléments dans <code>document</code>.
|
||
Ici, chaque exemple a sa petite zone blanche nommée <code>scene</code> : on écrit
|
||
<code>scene.querySelector(...)</code> pour ne toucher qu'elle. Le principe est identique.
|
||
</div>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>dom.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// 1. SÉLECTIONNER un élément avec un sélecteur CSS (comme dans style.css)
|
||
const titre = scene.querySelector("h4"); // par balise
|
||
const boite = scene.querySelector(".boite"); // par classe
|
||
const items = scene.querySelectorAll("li"); // TOUS les <li>
|
||
|
||
console.log(titre, boite, items.length);
|
||
|
||
// 2. MODIFIER le texte
|
||
titre.textContent = "Titre modifié par JavaScript ✨";
|
||
|
||
// 3. MODIFIER le style (propriétés CSS en camelCase : background-color → backgroundColor)
|
||
boite.style.backgroundColor = "#d4a017";
|
||
boite.style.padding = "12px";
|
||
boite.style.borderRadius = "8px";
|
||
|
||
// 4. AJOUTER / RETIRER des classes CSS (mieux que style : on garde le CSS dans le CSS)
|
||
boite.classList.add("important");
|
||
console.log(boite.classList.contains("important")); // true
|
||
|
||
// 5. MODIFIER chaque élément d'une liste
|
||
items.forEach((li, i) => {
|
||
li.textContent = `Élément n°${i + 1} (modifié)`;
|
||
});
|
||
|
||
// 6. CRÉER un nouvel élément et l'ajouter dans la page
|
||
const nouveau = document.createElement("p"); // crée <p></p> (pas encore affiché)
|
||
nouveau.textContent = "Je viens d'être créé !";
|
||
scene.append(nouveau); // l'insère à la fin de la scène
|
||
|
||
// 7. Lire / modifier un attribut
|
||
const lien = scene.querySelector("a");
|
||
lien.setAttribute("href", "https://developer.mozilla.org/fr/");
|
||
lien.textContent = "Documentation MDN";
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
<div class="scene">
|
||
<h4>Un titre</h4>
|
||
<div class="boite">Une boîte</div>
|
||
<ul><li>un</li><li>deux</li><li>trois</li></ul>
|
||
<a href="#">un lien</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="encadre attention">
|
||
<strong>textContent ou innerHTML ?</strong>
|
||
<code>innerHTML</code> interprète le texte comme du HTML (<code>"<b>gras</b>"</code>
|
||
devient <b>gras</b>). Pratique, mais dangereux avec du texte tapé par un utilisateur :
|
||
il pourrait injecter du code (faille « XSS »). Par défaut, utilise <code>textContent</code>.
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch11">
|
||
<h2><span class="num">11</span>Les événements : réagir à l'utilisateur</h2>
|
||
|
||
<p>
|
||
Un <strong>événement</strong>, c'est quelque chose qui se produit : un clic, une touche
|
||
pressée, la souris qui bouge, un formulaire envoyé… On demande au navigateur :
|
||
« <em>quand</em> tel événement arrive sur tel élément, <em>exécute</em> cette fonction ».
|
||
C'est le rôle de <code>addEventListener</code> (« ajouter un écouteur »).
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>evenements.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// Exécute ce code, PUIS clique sur les éléments de la zone blanche ↓
|
||
|
||
const bouton = scene.querySelector("#compteur");
|
||
const champ = scene.querySelector("#champ");
|
||
const apercu = scene.querySelector("#apercu");
|
||
const carre = scene.querySelector("#carre");
|
||
|
||
// --- Un compteur de clics ---
|
||
let clics = 0; // l'ÉTAT : une variable qui garde la mémoire entre deux clics
|
||
|
||
bouton.addEventListener("click", () => {
|
||
clics++;
|
||
bouton.textContent = `Cliqué ${clics} fois`;
|
||
console.log("clic !", clics);
|
||
});
|
||
|
||
// --- Réagir à la saisie ---
|
||
// "input" se déclenche à chaque caractère tapé
|
||
champ.addEventListener("input", (evenement) => {
|
||
// evenement.target = l'élément qui a déclenché l'événement
|
||
const texte = evenement.target.value;
|
||
apercu.textContent = texte.toUpperCase() || "(vide)";
|
||
});
|
||
|
||
// --- Survol de la souris ---
|
||
carre.addEventListener("mouseenter", () => carre.style.transform = "rotate(45deg) scale(1.2)");
|
||
carre.addEventListener("mouseleave", () => carre.style.transform = "");
|
||
|
||
// --- Position de la souris ---
|
||
carre.addEventListener("mousemove", (e) => {
|
||
// offsetX / offsetY : position dans l'élément, en pixels
|
||
carre.textContent = `${e.offsetX},${e.offsetY}`;
|
||
});
|
||
|
||
console.log("Écouteurs installés. À toi de jouer !");
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
<div class="scene">
|
||
<p><button id="compteur" type="button">Clique-moi</button></p>
|
||
<p><input id="champ" placeholder="Tape quelque chose…" aria-label="Champ de test"> → <strong id="apercu">(vide)</strong></p>
|
||
<div id="carre" style="width:80px;height:80px;background:#3b7dd8;color:#fff;display:grid;place-items:center;font-size:12px;transition:transform .3s;border-radius:8px">survole</div>
|
||
</div>
|
||
</div>
|
||
|
||
<h3>Les événements les plus utiles</h3>
|
||
<table>
|
||
<tr><th>Événement</th><th>Se déclenche quand…</th></tr>
|
||
<tr><td><code>click</code></td><td>on clique</td></tr>
|
||
<tr><td><code>input</code></td><td>la valeur d'un champ change (à chaque frappe)</td></tr>
|
||
<tr><td><code>submit</code></td><td>un formulaire est envoyé (penser à <code>e.preventDefault()</code>)</td></tr>
|
||
<tr><td><code>keydown</code></td><td>une touche est enfoncée (<code>e.key</code> dit laquelle)</td></tr>
|
||
<tr><td><code>mouseenter</code> / <code>mouseleave</code></td><td>la souris entre / sort</td></tr>
|
||
<tr><td><code>scroll</code></td><td>on fait défiler</td></tr>
|
||
<tr><td><code>DOMContentLoaded</code></td><td>le HTML est entièrement chargé</td></tr>
|
||
</table>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch12">
|
||
<h2><span class="num">12</span>L'asynchrone : gérer le temps qui passe</h2>
|
||
|
||
<p>
|
||
Jusqu'ici, tout s'exécutait instantanément, dans l'ordre. Mais certaines actions
|
||
<strong>prennent du temps</strong> : attendre 2 secondes, télécharger des données
|
||
sur internet… JavaScript ne bloque pas la page en attendant : il <strong>continue</strong>
|
||
et revient plus tard quand le résultat est prêt. C'est l'<strong>asynchrone</strong>.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>timers.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
console.log("1. Début");
|
||
|
||
// setTimeout(fonction, délai en millisecondes) : exécute la fonction PLUS TARD
|
||
setTimeout(() => {
|
||
console.log("3. …1 seconde plus tard");
|
||
}, 1000);
|
||
|
||
console.log("2. Fin du code… mais ce n'est pas fini !");
|
||
// Remarque l'ordre d'affichage : 1, 2, puis 3.
|
||
// JS n'attend pas le setTimeout : il programme la fonction et continue.
|
||
|
||
// setInterval : répète toutes les X ms. clearInterval l'arrête.
|
||
let n = 0;
|
||
const minuterie = setInterval(() => {
|
||
n++;
|
||
console.log("tic", n);
|
||
if (n === 3) clearInterval(minuterie);
|
||
}, 500);
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>Les promesses et async / await</h3>
|
||
<p>
|
||
Une <strong>Promise</strong> (promesse) est un objet qui représente un résultat
|
||
<em>futur</em> : « je n'ai pas encore la réponse, mais je te promets de te la donner
|
||
(ou de te dire que ça a échoué) ». Le mot-clé <code>await</code> permet
|
||
<strong>d'attendre</strong> une promesse, dans une fonction marquée <code>async</code>.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>async-await.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// Une fonction qui renvoie une promesse résolue après "ms" millisecondes
|
||
function attendre(ms) {
|
||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||
}
|
||
|
||
// Simule une commande au restaurant qui peut échouer
|
||
function commander(plat) {
|
||
return new Promise((resolve, reject) => {
|
||
setTimeout(() => {
|
||
if (plat === "licorne") {
|
||
reject(new Error("Plat introuvable 🦄")); // échec
|
||
} else {
|
||
resolve(`🍽 ${plat} servi !`); // succès
|
||
}
|
||
}, 800);
|
||
});
|
||
}
|
||
|
||
// async : cette fonction peut utiliser await
|
||
async function repas() {
|
||
console.log("On s'installe…");
|
||
await attendre(500); // ⏸ on attend ici (sans bloquer la page !)
|
||
console.log("On commande.");
|
||
|
||
const plat = await commander("pizza"); // await "déballe" la promesse
|
||
console.log(plat);
|
||
|
||
// try / catch pour gérer l'échec d'une promesse
|
||
try {
|
||
const autre = await commander("licorne");
|
||
console.log(autre);
|
||
} catch (erreur) {
|
||
console.warn("Problème :", erreur.message);
|
||
}
|
||
console.log("L'addition, s'il vous plaît.");
|
||
}
|
||
|
||
repas();
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<h3>fetch : récupérer des données sur internet</h3>
|
||
<p>
|
||
<code>fetch(url)</code> envoie une requête à un serveur et renvoie une promesse.
|
||
On récupère le plus souvent du <strong>JSON</strong> (chapitre 9).
|
||
Ici, on interroge une API de test gratuite (connexion internet nécessaire).
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>fetch.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
const liste = scene.querySelector("ul");
|
||
liste.innerHTML = "<li>Chargement…</li>";
|
||
|
||
try {
|
||
// 1. On envoie la requête et on ATTEND la réponse du serveur
|
||
const reponse = await fetch("https://jsonplaceholder.typicode.com/users");
|
||
|
||
// 2. On vérifie que tout s'est bien passé (code HTTP 200-299)
|
||
if (!reponse.ok) throw new Error("Erreur HTTP " + reponse.status);
|
||
|
||
// 3. On transforme le corps de la réponse (texte JSON) en vrais objets JS
|
||
const utilisateurs = await reponse.json();
|
||
console.log(`${utilisateurs.length} utilisateurs reçus`);
|
||
console.log("Le premier :", utilisateurs[0].name, "-", utilisateurs[0].email);
|
||
|
||
// 4. On les affiche dans la page
|
||
liste.innerHTML = ""; // on vide
|
||
for (const u of utilisateurs.slice(0, 5)) { // les 5 premiers seulement
|
||
const li = document.createElement("li");
|
||
li.textContent = `${u.name} (${u.address.city})`;
|
||
liste.append(li);
|
||
}
|
||
} catch (erreur) {
|
||
// Pas de connexion, serveur en panne…
|
||
liste.innerHTML = "<li>Impossible de charger les données.</li>";
|
||
console.error(erreur.message);
|
||
}
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
<div class="scene"><ul><li>(rien encore)</li></ul></div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch13">
|
||
<h2><span class="num">13</span>Les classes : des moules à objets</h2>
|
||
|
||
<p>
|
||
Quand on doit créer beaucoup d'objets du même genre (des ennemis dans un jeu, des
|
||
produits dans une boutique…), on écrit un <strong>moule</strong> : une
|
||
<strong>classe</strong>. Chaque objet fabriqué avec est une <strong>instance</strong>.
|
||
C'est la base de la <em>programmation orientée objet</em>.
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>classes.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
class Animal {
|
||
// constructor est appelé automatiquement à chaque "new Animal(...)"
|
||
constructor(nom, cri) {
|
||
this.nom = nom; // "this" = l'objet en cours de fabrication
|
||
this.cri = cri;
|
||
this.energie = 10;
|
||
}
|
||
|
||
// une méthode, partagée par toutes les instances
|
||
parler() {
|
||
console.log(`${this.nom} fait « ${this.cri} »`);
|
||
}
|
||
|
||
manger(quantite = 1) {
|
||
this.energie += quantite;
|
||
return this; // renvoyer "this" permet d'enchaîner : a.manger().manger()
|
||
}
|
||
}
|
||
|
||
// "new" fabrique une instance à partir de la classe
|
||
const chat = new Animal("Minou", "miaou");
|
||
const vache = new Animal("Marguerite", "meuh");
|
||
chat.parler();
|
||
vache.parler();
|
||
chat.manger(2).manger(3);
|
||
console.log(chat.nom, "a", chat.energie, "d'énergie");
|
||
|
||
// --- HÉRITAGE : une classe qui étend une autre ---
|
||
class Chien extends Animal {
|
||
constructor(nom) {
|
||
super(nom, "wouf"); // super(...) appelle le constructeur du PARENT
|
||
this.tours = [];
|
||
}
|
||
apprendre(tour) {
|
||
this.tours.push(tour);
|
||
console.log(`${this.nom} sait maintenant : ${this.tours.join(", ")}`);
|
||
}
|
||
// On peut REDÉFINIR une méthode du parent
|
||
parler() {
|
||
super.parler(); // on garde le comportement du parent…
|
||
console.log("(et remue la queue)"); // …et on en ajoute
|
||
}
|
||
}
|
||
|
||
const rex = new Chien("Rex");
|
||
rex.parler();
|
||
rex.apprendre("assis");
|
||
rex.apprendre("couché");
|
||
console.log(rex instanceof Chien, rex instanceof Animal); // true true
|
||
console.log(rex);
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch14">
|
||
<h2><span class="num">14</span>Mini-projet : le jeu du nombre mystère</h2>
|
||
|
||
<p>
|
||
On rassemble <strong>tout</strong> : variables, conditions, fonctions, DOM, événements.
|
||
L'ordinateur choisit un nombre entre 1 et 100 ; le joueur doit le deviner en un minimum
|
||
d'essais. Exécute, joue, puis lis le code et améliore-le !
|
||
</p>
|
||
|
||
<div class="bac">
|
||
<div class="barre"><span>jeu.js</span>
|
||
<div class="boutons"><button class="reinit" type="button">↺</button><button class="executer" type="button">▶ Exécuter</button></div></div>
|
||
<textarea aria-label="Éditeur de code">
|
||
// ====== 1. LES ÉLÉMENTS DE LA PAGE ======
|
||
const formulaire = scene.querySelector("form");
|
||
const champ = scene.querySelector("input");
|
||
const message = scene.querySelector(".message");
|
||
const historique = scene.querySelector(".historique");
|
||
const rejouer = scene.querySelector(".rejouer");
|
||
|
||
// ====== 2. L'ÉTAT DU JEU ======
|
||
// Tout ce dont le jeu doit "se souvenir" pendant la partie
|
||
const MAX = 100; // constante en MAJUSCULES : convention pour un réglage
|
||
let mystere; // le nombre à trouver
|
||
let essais; // nombre de tentatives
|
||
let termine; // la partie est-elle finie ?
|
||
|
||
// ====== 3. LES FONCTIONS ======
|
||
|
||
// Renvoie un entier aléatoire entre 1 et max (inclus)
|
||
function nombreAleatoire(max) {
|
||
// Math.random() → nombre à virgule entre 0 (inclus) et 1 (exclu)
|
||
// × max → entre 0 et max ; Math.floor arrondit vers le bas ; +1 → de 1 à max
|
||
return Math.floor(Math.random() * max) + 1;
|
||
}
|
||
|
||
function afficher(texte, couleur) {
|
||
message.textContent = texte;
|
||
message.style.color = couleur;
|
||
}
|
||
|
||
function nouvellePartie() {
|
||
mystere = nombreAleatoire(MAX);
|
||
essais = 0;
|
||
termine = false;
|
||
historique.textContent = "";
|
||
rejouer.hidden = true; // cache le bouton "rejouer"
|
||
champ.disabled = false;
|
||
champ.value = "";
|
||
champ.focus(); // place le curseur dans le champ
|
||
afficher(`J'ai choisi un nombre entre 1 et ${MAX}. À toi !`, "inherit");
|
||
console.log("(triche) le nombre est", mystere);
|
||
}
|
||
|
||
function verifier(proposition) {
|
||
// Garde-fous : on refuse les saisies invalides
|
||
if (Number.isNaN(proposition) || proposition < 1 || proposition > MAX) {
|
||
afficher(`Entre un nombre entre 1 et ${MAX} !`, "#d64545");
|
||
return; // on sort de la fonction tout de suite
|
||
}
|
||
|
||
essais++;
|
||
historique.textContent += proposition + " ";
|
||
|
||
if (proposition === mystere) {
|
||
afficher(`🎉 Bravo ! Trouvé en ${essais} essai${essais > 1 ? "s" : ""}.`, "#2f9e5b");
|
||
termine = true;
|
||
champ.disabled = true;
|
||
rejouer.hidden = false;
|
||
} else if (proposition < mystere) {
|
||
afficher("C'est plus ⬆", "#d4a017");
|
||
} else {
|
||
afficher("C'est moins ⬇", "#d4a017");
|
||
}
|
||
}
|
||
|
||
// ====== 4. LES ÉVÉNEMENTS ======
|
||
formulaire.addEventListener("submit", (e) => {
|
||
e.preventDefault(); // empêche le rechargement de la page (comportement par défaut d'un form)
|
||
if (termine) return;
|
||
verifier(Number(champ.value)); // ⚠ value est un TEXTE : on convertit !
|
||
champ.value = "";
|
||
champ.focus();
|
||
});
|
||
|
||
rejouer.addEventListener("click", nouvellePartie); // on passe la fonction, SANS ()
|
||
|
||
// ====== 5. LANCEMENT ======
|
||
nouvellePartie();
|
||
|
||
/* 💪 IDÉES D'AMÉLIORATION :
|
||
- Limiter à 7 essais, puis "Perdu ! C'était X"
|
||
- Garder le meilleur score (une variable en dehors de nouvellePartie)
|
||
- Dire "Tu chauffes 🔥" si on est à moins de 5 du nombre
|
||
- Ajouter un choix de difficulté (MAX = 10, 100 ou 1000)
|
||
*/
|
||
</textarea>
|
||
<div class="sortie" aria-live="polite"></div>
|
||
<div class="scene">
|
||
<form>
|
||
<label>Ta proposition : <input type="number" min="1" max="100" style="width:90px"></label>
|
||
<button type="submit">Valider</button>
|
||
<button type="button" class="rejouer" hidden>Rejouer</button>
|
||
</form>
|
||
<p class="message" style="font-weight:600">Clique sur « Exécuter » pour lancer le jeu.</p>
|
||
<p>Essais : <span class="historique"></span></p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- ======================================================== -->
|
||
<section class="chapitre" id="ch15">
|
||
<h2><span class="num">15</span>Et après ?</h2>
|
||
|
||
<h3>Récapitulatif</h3>
|
||
<table>
|
||
<tr><th>Notion</th><th>À retenir</th></tr>
|
||
<tr><td>Variables</td><td><code>const</code> par défaut, <code>let</code> si ça change</td></tr>
|
||
<tr><td>Comparaison</td><td>Toujours <code>===</code> et <code>!==</code></td></tr>
|
||
<tr><td>Fonctions</td><td>Petites, un seul rôle, un nom qui dit ce qu'elles font</td></tr>
|
||
<tr><td>Tableaux</td><td><code>map</code>, <code>filter</code>, <code>find</code>, <code>reduce</code></td></tr>
|
||
<tr><td>DOM</td><td><code>querySelector</code>, <code>textContent</code>, <code>classList</code></td></tr>
|
||
<tr><td>Événements</td><td><code>addEventListener("click", fonction)</code></td></tr>
|
||
<tr><td>Asynchrone</td><td><code>async</code> / <code>await</code> + <code>try</code> / <code>catch</code></td></tr>
|
||
</table>
|
||
|
||
<h3>Comment progresser</h3>
|
||
<ul>
|
||
<li><strong>Lis les erreurs</strong> : elles disent presque toujours où et pourquoi.</li>
|
||
<li><strong><code>console.log</code> partout</strong> quand tu ne comprends pas ce qui se passe.</li>
|
||
<li><strong>Découpe</strong> : un gros problème = plein de petits problèmes faciles.</li>
|
||
<li><strong>Copie moins, tape plus</strong> : écrire le code soi-même ancre la mémoire.</li>
|
||
<li><strong>Relis <code>script.js</code></strong> de cette page : tu sais maintenant tout lire !</li>
|
||
</ul>
|
||
|
||
<h3>Ressources</h3>
|
||
<ul>
|
||
<li><a href="https://developer.mozilla.org/fr/docs/Learn/JavaScript">MDN Web Docs</a> — la référence, en français</li>
|
||
<li><a href="https://fr.javascript.info/">javascript.info</a> — tutoriel complet et clair</li>
|
||
<li><a href="https://p5js.org/">p5.js</a> — dessiner et animer avec JS, idéal en école d'art</li>
|
||
<li><a href="https://codepen.io/">CodePen</a> — tester HTML/CSS/JS en ligne et partager</li>
|
||
</ul>
|
||
|
||
<div class="exercice">
|
||
<strong>Défi final</strong> — Crée ta propre page (un nouveau dossier avec
|
||
<code>index.html</code>, <code>style.css</code>, <code>script.js</code>) : une liste de
|
||
tâches où l'on peut ajouter une tâche via un champ, la cocher (classe CSS « faite »)
|
||
et la supprimer. Tout ce qu'il faut est dans les chapitres 8, 10 et 11.
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
</div>
|
||
</body>
|
||
</html>
|