Module JS.10 – Bonnes pratiques
Objectif
Appliquer les bonnes pratiques JavaScript : scope, immutabilité, modularisation, et conventions pour créer du code professionnel et maintenable.
Théorie
Scope (Portée)
Scope global
Variables déclarées en dehors de toute fonction.
const globale = "Je suis globale";
function test() {
console.log(globale); // Accessible
}
Problème : Pollution de l'espace de noms global.
Scope de fonction
Variables déclarées dans une fonction.
function test() {
const locale = "Je suis locale";
console.log(locale); // Accessible
}
console.log(locale); // Erreur : non accessible
Scope de bloc
Variables déclarées avec let ou const dans un bloc.
if (true) {
const bloc = "Je suis dans un bloc";
console.log(bloc); // Accessible
}
console.log(bloc); // Erreur : non accessible
Hoisting
var : Hoisted et initialisé à undefined
console.log(x); // undefined (pas d'erreur)
var x = 5;
let/const : Hoisted mais pas initialisé (Temporal Dead Zone)
console.log(x); // Erreur : Cannot access before initialization
let x = 5;
function : Hoisted complètement
test(); // Fonctionne
function test() {
console.log("Test");
}
Immutabilité
Éviter de modifier les données existantes, créer de nouvelles à la place.
Pourquoi l'immutabilité ?
- Prédictibilité
- Évite les bugs de mutation
- Facilite le débogage
- Compatible avec React, Redux
Techniques
Copies superficielles :
const original = { nom: "Jean", age: 30 };
// Spread operator
const copie = { ...original };
// Object.assign
const copie2 = Object.assign({}, original);
Copies profondes :
// JSON (limité aux types JSON)
const copieProfonde = JSON.parse(JSON.stringify(original));
// Structured Clone (moderne)
const copieProfonde2 = structuredClone(original);
// Bibliothèque (lodash)
const copieProfonde3 = _.cloneDeep(original);
Tableaux immutables :
const nombres = [1, 2, 3];
// ❌ Mutation
nombres.push(4); // Modifie l'original
// ✅ Immutable
const nouveaux = [...nombres, 4]; // Nouveau tableau
const sansPremier = nombres.slice(1); // Nouveau tableau
const doubles = nombres.map(n => n * 2); // Nouveau tableau
Modularisation
Organiser le code en modules réutilisables.
Modules ES6
Export :
// math.js
export function additionner(a, b) {
return a + b;
}
export const PI = 3.14159;
export default function multiplier(a, b) {
return a * b;
}
Import :
// app.js
import multiplier, { additionner, PI } from './math.js';
// Import avec alias
import { additionner as add } from './math.js';
// Import tout
import * as math from './math.js';
math.additionner(1, 2);
CommonJS (Node.js)
// math.js
exports.additionner = function(a, b) {
return a + b;
};
module.exports = {
multiplier: function(a, b) {
return a * b;
}
};
// app.js
const { additionner } = require('./math');
const math = require('./math');
Conventions de nommage
Variables et fonctions : camelCase
const nomUtilisateur = "Jean";
function calculerMoyenne() {}
Classes : PascalCase
class Personne {}
class GestionnaireUtilisateurs {}
Constantes : UPPER_SNAKE_CASE
const MAX_SIZE = 100;
const API_URL = "https://api.exemple.com";
Privé (convention) : _underscore
class Personne {
_agePrive = 30; // Convention (pas vraiment privé)
}
Code propre
Noms descriptifs
// ❌ Mauvais
const d = new Date();
function calc(a, b) {}
// ✅ Bon
const dateActuelle = new Date();
function calculerMoyenne(nombres) {}
Fonctions courtes et focalisées
// ❌ Mauvais : fait trop de choses
function traiterDonnees(donnees) {
// Validation
// Transformation
// Sauvegarde
// Envoi email
// ...
}
// ✅ Bon : une responsabilité
function validerDonnees(donnees) {}
function transformerDonnees(donnees) {}
function sauvegarderDonnees(donnees) {}
DRY (Don't Repeat Yourself)
// ❌ Répétition
function calculerPrixTTC1(prix) {
return prix * 1.20;
}
function calculerPrixTTC2(prix) {
return prix * 1.20;
}
// ✅ Réutilisable
const TAUX_TVA = 1.20;
function calculerPrixTTC(prix) {
return prix * TAUX_TVA;
}
Commentaires utiles
// ❌ Mauvais : explique le "comment"
// Incrémente i de 1
i++;
// ✅ Bon : explique le "pourquoi"
// Réinitialise le compteur pour le prochain lot
i = 0;
Linting et formatage
ESLint : Détecte les erreurs et problèmes de style
{
"rules": {
"no-var": "error",
"prefer-const": "error",
"no-console": "warn"
}
}
Prettier : Formate le code automatiquement
Performance
Éviter les opérations coûteuses
// ❌ Mauvais : recalcul à chaque fois
function calculerTotal(items) {
return items
.filter(i => i.actif)
.map(i => i.prix)
.reduce((sum, p) => sum + p, 0);
}
// ✅ Bon : cache si possible
const cache = new Map();
function calculerTotal(items) {
const cle = JSON.stringify(items);
if (cache.has(cle)) {
return cache.get(cle);
}
const total = items
.filter(i => i.actif)
.map(i => i.prix)
.reduce((sum, p) => sum + p, 0);
cache.set(cle, total);
return total;
}
Éviter les fuites mémoire
// Nettoyer les event listeners
const bouton = document.getElementById('btn');
bouton.addEventListener('click', handler);
// Plus tard
bouton.removeEventListener('click', handler);
// Nettoyer les timers
const timerId = setInterval(() => {}, 1000);
clearInterval(timerId);
Exercice
-
Scope
- Testez les différents scopes
- Comprenez le hoisting
- Évitez la pollution globale
-
Immutabilité
- Créez des copies au lieu de mutations
- Utilisez spread operator
- Testez les copies profondes
-
Modularisation
- Créez des modules ES6
- Organisez votre code
- Importez/exportez correctement
-
Conventions
- Appliquez les conventions de nommage
- Refactorisez du code existant
- Améliorez la lisibilité
-
Code propre
- Refactorisez selon les principes
- Éliminez la duplication
- Améliorez les noms
Quiz
-
Quel est le scope de let et const ?
- Global
- Bloc
- Fonction
-
Que fait le spread operator avec les objets ?
- Modifie l'original
- Crée une copie
- Supprime les propriétés
-
Comment exporter une fonction en ES6 ?
- exports.function
- export function
- module.exports
-
Quelle convention pour les constantes ?
- camelCase
- UPPER_SNAKE_CASE
- PascalCase
-
Que signifie DRY ?
- Don't Repeat Yourself
- Don't Repeat Yourself
- Do Repeat Yourself
Mini défi
Mission : Refactoriser un projet selon les bonnes pratiques
Prenez un projet JavaScript existant (ou créez-en un) et refactorisez-le :
Améliorations à apporter :
-
Modularisation
- Séparez en modules ES6
- Organisez par fonctionnalité
- Importez/exportez correctement
-
Immutabilité
- Remplacez les mutations par des copies
- Utilisez spread operator
- Créez de nouvelles structures au lieu de modifier
-
Scope et variables
- Utilisez const par défaut
- Évitez var
- Minimisez le scope global
-
Code propre
- Noms descriptifs
- Fonctions courtes et focalisées
- Éliminez la duplication (DRY)
-
Conventions
- Respectez les conventions de nommage
- Commentaires utiles
- Structure claire
Critères :
- ✅ Code modulaire et organisé
- ✅ Immutabilité respectée
- ✅ Conventions appliquées
- ✅ Code propre et maintenable
- ✅ Documentation appropriée
Objectif : Appliquer toutes les bonnes pratiques pour créer du code professionnel et maintenable.
Validation : Vous pouvez passer au module suivant quand votre code respecte les bonnes pratiques et est bien organisé.