Classes et modules JavaScript et outils de développement

Découvre comment sont organisés les projets JavaScript professionnels. Construis des objets avec des classes, des champs privés et l’héritage, et découvre la chaîne de prototypes sur laquelle reposent les classes. Répartis le code en modules ES exécutables dans le navigateur et dans Node.js, gère les paquets avec npm et package.json, et utilise les outils courants d’un environnement de travail moderne : un linter et un formateur de code, un serveur de développement et un bundler, ainsi qu’un exécuteur de tests. Termine en découvrant la place de TypeScript et des frameworks front-end dans cette chaîne d’outils.

DébutantUnité 9 sur 9 de la formation Formation : JavaScript : DOM, événements et code asynchrone

Ce que tu vas apprendre

  1. Utilise des classes pour créer des objets aux comportements communs, protéger leurs données et construire des hiérarchies par héritage, puis explique la chaîne de prototypes sur laquelle reposent les classes.
    • Définis une classe et crée des objets avec new
      Écris une classe avec un constructeur, des champs, des méthodes et des accesseurs en lecture et en écriture, crée des instances avec new et veille à ce que this désigne le bon objet.
    • Protège les données avec des membres privés et partage des valeurs avec des membres statiques
      Masque l’état interne d’un objet derrière des champs et des méthodes privés, et place dans des membres statiques les valeurs et fonctions utilitaires qui appartiennent à la classe dans son ensemble.
    • Construis des hiérarchies de classes avec extends et super
      Crée des sous-classes qui héritent de comportements et les redéfinissent, appelle la classe parente avec super, vérifie les types avec instanceof et détermine quand l’héritage ou la composition convient le mieux.
    • Explique le rôle des prototypes dans les objets et les classes
      Décris comment JavaScript recherche les propriétés dans la chaîne de prototypes, comment les classes et extends établissent cette chaîne et pourquoi les prototypes intégrés ne sont pas modifiés.
  2. Répartis un programme en modules qui exportent et importent des fonctionnalités, exécute-les dans les navigateurs et dans Node.js, charge le code à la demande et donne à chaque module un rôle clair.
    • Exporte et importe du code entre fichiers
      Répartis un programme en modules ES et relie-les avec des exportations nommées et par défaut, des importations renommées ou dans un espace de noms, et des réexportations, en comprenant le fonctionnement de la portée de module et des liaisons dynamiques.
    • Exécute des modules dans le navigateur et dans Node.js
      Charge des modules dans une page web avec type="module" depuis un serveur local, résous les chemins et les noms nus des modules, et comprends comment Node.js choisit entre les modules ES et CommonJS.
    • Charge des modules à la demande et organise un projet en modules
      Utilise l’importation dynamique avec import() et await au niveau supérieur, répartis une application en modules ciblés et évite les problèmes liés aux effets de bord et aux importations circulaires.
  3. Décris un projet dans package.json, exécute ses tâches avec des scripts npm, puis installe, mets à jour et choisis les dépendances afin que chaque ordinateur obtienne le même ensemble de paquets fonctionnel.
    • Configure un projet avec npm et package.json
      Crée un projet avec npm init, lis et modifie les principaux champs de package.json, exécute des tâches avec des scripts npm et npx, et lis les numéros de version sémantique.
    • Installe, mets à jour et choisis des dépendances
      Installe des paquets comme dépendances d’exécution ou de développement, lis les plages de versions, utilise package-lock.json et npm ci pour obtenir des installations reproductibles, maintiens les dépendances à jour et choisis les paquets en toute sécurité.
  4. Utilise un linter et un formateur de code pour repérer les problèmes et garder un style cohérent, un serveur de développement et un bundler pour exécuter et livrer un projet, et un exécuteur de tests pour vérifier que le code fonctionne.
    • Repère les problèmes avec un linter et mets le code en forme automatiquement
      Utilise ESLint pour trouver des bogues probables sans exécuter le code et Prettier pour garder une mise en forme cohérente, configure les deux et lance-les depuis des scripts et l’éditeur.
    • Sers et regroupe les fichiers d’un projet avec un serveur de développement et un bundler
      Explique le rôle des bundlers et des serveurs de développement, exécute le cycle de développement, compilation et prévisualisation avec Vite, et comprends le tree shaking, la minification, les noms de fichiers avec empreinte, les cartes des sources et les variables d’environnement.
    • Vérifie le code automatiquement avec un exécuteur de tests
      Écris des tests unitaires avec des assertions pour des fonctions et des classes, exécute-les avec l’exécuteur de tests intégré à Node.js ou avec Vitest, lis les échecs et conçois du code facile à tester.
  5. Explique ce que TypeScript et les frameworks front-end ajoutent à JavaScript, comment ils utilisent les modules, npm et les outils de compilation, et comment tous ces outils fonctionnent ensemble dans un projet.
    • Explique ce que TypeScript apporte à JavaScript
      Décris comment les types statiques de TypeScript repèrent les erreurs avant l’exécution du code, comment le code TypeScript devient du JavaScript et quand son adoption justifie cette étape supplémentaire.
    • Situe les frameworks dans une chaîne d’outils moderne complète
      Explique le rôle des frameworks front-end et comment ils s’appuient sur les modules, npm et les bundlers, puis réunis les outils de cette unité dans une méthode de travail courante.

Classes et modules JavaScript : cours

5 chapitres

1

Construis des objets qui partagent des comportements

Un objet ordinaire regroupe des valeurs liées. Une classe ajoute un moyen reproductible de créer des objets avec leurs propres données et des comportements partagés. Commence par les constructeurs et les méthodes, puis contrôle les modifications au moyen de champs privés et d’une interface publique. L’héritage permet à des classes apparentées de spécialiser ce comportement. La chaîne de prototypes explique comment JavaScript trouve les méthodes et pourquoi une instance peut utiliser du code stocké ailleurs.

1.1 Crée et utilise des instances de classe

Une classe décrit des objets de même structure et de même comportement. Chaque objet créé à partir de celle-ci est une instance. Utilise une classe lorsque plusieurs objets ont besoin des mêmes opérations ; un objet ordinaire suffit souvent pour une valeur de configuration ponctuelle.

Donne à chaque objet ses propres données

Par convention, les noms de classes utilisent PascalCase, comme Rectangle. Le constructor s’exécute chaque fois que new crée une instance. À l’intérieur, this désigne le nouvel objet. Une affectation à this.width stocke une propriété d’instance ; un paramètre nommé width seul n’est qu’une variable locale.

class Rectangle {
  constructor(width, height) {
    this.width = width; // cm
    this.height = height;
  }
  area() {
    return this.width * this.height;
  }
  perimeter() {
    return 2 * (this.width + this.height);
  }
}
const a = new Rectangle(3, 4);
const b = new Rectangle(5, 2);
a.area();      // 12
a.perimeter(); // 14
b.area();      // 10

Pour a.area(), JavaScript appelle la méthode en donnant à this la valeur a. Multiplier sa largeur, 3 cm, par sa hauteur, 4 cm, donne 12 cm². Le périmètre s’obtient en additionnant les deux côtés différents et en doublant cette somme, soit 14 cm. Modifier b.width ne modifie que b.

Les méthodes n’ont pas de mot-clé function et ne sont pas séparées par des virgules. Une classe a au plus un constructeur. Pour une classe sans extends, l’omission du constructeur donne un constructeur par défaut vide. new renvoie automatiquement l’instance créée.

Un champ déclare une propriété dans le corps de la classe : unit = "cm"; donne à chaque instance sa propre valeur. label; vaut initialement undefined. Dans une classe sans extends, les champs d’instance sont initialisés avant l’exécution du corps du constructeur.

Lis et affecte des valeurs par des accesseurs

Un accesseur en lecture s’exécute lorsqu’une propriété est lue. Avec get area() { return this.width * this.height; }, lis a.area sans parenthèses. C’est une alternative à la méthode ci-dessus, qui utilise a.area().

Un accesseur en écriture s’exécute lors d’une affectation et peut rejeter une entrée invalide. Il doit stocker la valeur séparément : set width(value) { this.width = value; } se rappelle sans cesse jusqu’au débordement de la pile. Stocke la valeur sous un autre nom, comme le champ privé #width.

Conserve l’objet receveur lors du passage d’une méthode
class Counter {
  count = 0;
  increment() { this.count++; }
}
const counter = new Counter();
const inc = counter.increment;
// inc(); // TypeError: this is undefined
const safeInc = () => counter.increment();
safeInc(); // counter.count is 1

Les méthodes de classe s’exécutent en mode strict. Un appel détaché n’a pas d’objet receveur avant le point : this vaut donc undefined. L’appelant d’une fonction de rappel peut aussi fournir un autre objet receveur. Une fonction fléchée enveloppante préserve l’appel sur counter ; counter.increment.bind(counter) crée une fonction liée. Un champ contenant une fonction fléchée, increment = () => { this.count++; };, capture également le this de l’instance.

Appeler Rectangle(3, 4) sans new lève une TypeError. Utiliser une classe avant que sa déclaration ne soit initialisée lève une ReferenceError. Les classes diffèrent ici des déclarations de fonctions, qui peuvent être appelées plus haut dans un fichier.

JSON conserve les données, pas le comportement de la classe. JSON.stringify(a) enregistre ses propriétés propres publiques de largeur et de hauteur. L’analyse de ce texte crée un objet ordinaire ; reconstruis une instance avec new Rectangle(data.width, data.height) pour utiliser ses méthodes.

Points clés

  • new crée une instance et exécute son constructeur ; this désigne l’objet receveur d’un appel de méthode.
  • Les champs contiennent les données propres à chaque instance ; les méthodes ordinaires sont partagées.
  • Les accesseurs en lecture se lisent comme des propriétés ; les accesseurs en écriture s’exécutent lors d’une affectation et nécessitent un stockage distinct.
  • Utilise une fonction fléchée enveloppante ou une fonction liée lorsqu’une fonction de rappel doit conserver son objet receveur.
  • JSON ne restaure pas les méthodes de classe lors de l’analyse des données enregistrées.

1.2 Protège l’état avec des champs privés

Un objet peut proposer une petite interface publique tout en gardant son stockage privé. C’est l’encapsulation. L’interface détermine quelles modifications sont valides ; la confidentialité seule ne vérifie pas la valeur transmise à un accesseur en écriture public.

Place la validation à l’entrée

Un champ privé commence par # et doit être déclaré dans le corps de la classe. Le code de cette classe le lit avec this.#target. Le code extérieur ne peut ni lire ni modifier t.#target : c’est une erreur de syntaxe, pas une lecture de propriété qui renvoie undefined.

class Thermostat {
  static MIN = 10;
  static MAX = 30;
  #target = 20;

  get target() { return this.#target; }
  set target(value) {
    if (!Number.isFinite(value) ||
        value < Thermostat.MIN ||
        value > Thermostat.MAX) {
      throw new RangeError("Target must be between 10 and 30 °C");
    }
    this.#target = value;
  }
}
const t = new Thermostat();
t.target = 22;
t.target; // 22
// t.target = 35; // throws RangeError

L’accesseur en lecture expose une valeur sans exposer son stockage. L’accesseur en écriture rejette d’abord les entrées non finies ou non numériques, puis les valeurs hors de l’intervalle de 10 à 30 °C, bornes incluses. Seule une valeur acceptée atteint l’affectation. Après une tentative rejetée de définir 35 °C, la consigne reste à 22 °C. Une chaîne numérique comme "22" échoue également au test Number.isFinite.

Les accesseurs en lecture et en écriture utilisent #target : l’affectation à t.target ne rappelle donc pas récursivement l’accesseur en écriture. Les noms target et #target sont distincts. Un trait de soulignement initial, comme dans _target, demande seulement aux autres programmeurs de traiter une propriété publique comme interne ; JavaScript permet toujours d’y accéder.

Les champs privés n’apparaissent pas dans Object.keys, for...in ou la sérialisation JSON. Ce thermostat n’a pas de champs propres publics, donc JSON.stringify(t) produit "{}". L’enregistrement d’un objet peut donc nécessiter une méthode publique explicite qui renvoie les données à enregistrer.

Garde les fonctions auxiliaires internes privées

Une méthode comme #check(value) { ... } peut contenir des étapes de validation et s’appelle dans la classe avec this.#check(value). Elle ne fait pas partie de l’interface publique. Dans la classe, #target in obj teste si un objet possède ce champ privé.

Une sous-classe ne peut pas utiliser directement le nom privé de sa classe parente. Elle peut utiliser l’accesseur public en lecture ou en écriture de la classe parente, qui s’exécute dans la classe ayant déclaré le champ. La classe parente conserve ainsi le contrôle de son propre état.

Place le travail partagé sur la classe

Un membre statique appartient à la classe. Thermostat.MIN vaut 10, tandis que t.MIN vaut undefined. Ces bornes statiques sont des champs publics ; static ne les rend pas en lecture seule à lui seul.

class Tracked {
  static count = 0;
  constructor() { Tracked.count++; }
}
new Tracked();
new Tracked();
new Tracked();
Tracked.count; // 3

Chaque constructeur incrémente un même compteur au niveau de la classe. Un champ d’instance donnerait au contraire un compteur distinct à chaque objet. Une méthode de fabrique statique, comme static square(side) { return new Rectangle(side, side); }, se place dans Rectangle et s’appelle avec Rectangle.square(5). Une fonction de comparaison statique peut être transmise à sort lorsqu’elle prend les objets comparés comme arguments.

Dans une méthode statique, this désigne la classe sur laquelle elle a été appelée ; ce n’est pas une instance de rectangle ayant une largeur. Un bloc d’initialisation static { ... } effectue l’initialisation une fois lors de la définition de la classe et peut accéder aux membres privés de cette classe.

Points clés

  • La confidentialité des champs # est imposée par JavaScript ; le trait de soulignement n’est qu’une convention.
  • Valide les modifications par l’interface publique avant de changer l’état privé.
  • Les champs privés sont absents de l’énumération ordinaire des clés et de la sérialisation JSON.
  • Les sous-classes utilisent l’interface publique de la classe parente pour agir sur son état privé.
  • Appelle les membres statiques sur la classe ; ils ne contiennent pas les données propres à chaque instance.
  • Un bloc d’initialisation statique s’exécute une fois lorsque sa classe est définie.

1.3 Spécialise une classe avec l’héritage

L’héritage modélise une relation « est un ». Un cercle est une forme : une classe Circle peut donc hériter de la description commune d’une forme tout en fournissant son propre calcul d’aire. Une sous-classe hérite de comportements sans copier chaque méthode dans son corps.

Initialise d’abord la classe parente

class Circle extends Shape fait de Circle une sous-classe et de Shape sa superclasse. Dans le constructeur d’une sous-classe, super(...) appelle le constructeur de la classe parente. Cet appel doit s’exécuter avant la première utilisation de this. Une sous-classe sans constructeur en reçoit un qui transmet ses arguments à la classe parente.

class Shape {
  constructor(name) { this.name = name; }
  area() { return 0; }
  describe() {
    return this.name + " with area " +
      this.area().toFixed(2) + " cm²";
  }
}
class Circle extends Shape {
  constructor(radius) {
    super("Circle");
    this.radius = radius;
  }
  area() { return Math.PI * this.radius ** 2; }
}
class Rectangle extends Shape {
  constructor(width, height) {
    super("Rectangle");
    this.width = width;
    this.height = height;
  }
  area() { return this.width * this.height; }
}

L’appel new Circle(2).describe() donne "Circle with area 12.57 cm²". D’abord, super définit le nom. Le cercle stocke son rayon. La méthode héritée describe() appelle ensuite this.area(), qui trouve la méthode du cercle. toFixed(2) met le résultat en forme pour l’affichage. new Rectangle(3, 4).describe() donne "Rectangle with area 12.00 cm²".

Redéfinis ou étends une méthode

Une sous-classe redéfinit une méthode en déclarant une méthode de même nom. Elle peut appeler la version de la classe parente avec super.methodName().

class Square extends Rectangle {
  constructor(side) {
    super(side, side);
    this.name = "Square";
  }
  describe() {
    return super.describe() +
      " (all sides " + this.width + " cm)";
  }
}
new Square(5).describe();
// "Square with area 25.00 cm² (all sides 5 cm)"

super(side, side) initialise une largeur et une hauteur égales. La méthode d’aire héritée les multiplie et la méthode redéfinie ajoute des informations à la description héritée. Oublier les arguments nécessaires à la classe parente peut laisser ses propriétés à undefined ; appeler super() ne suffit pas si la classe parente a besoin de valeurs.

Le polymorphisme signifie qu’un même appel peut sélectionner des comportements différents. Une boucle peut appeler s.describe() sur des cercles et des rectangles ; chaque description appelle la méthode area() appropriée. Ajouter une forme avec sa propre méthode d’aire ne nécessite pas de nouveau cas dans cette boucle.

new Circle(2) instanceof Circle et new Circle(2) instanceof Shape sont tous deux vrais. Les membres statiques sont également hérités. La relation entre une instance et une classe suit sa chaîne de prototypes, que instanceof vérifie normalement.

Choisis une relation adaptée

Une classe ne peut étendre qu’une seule classe parente. Pour une relation « possède un », utilise la composition : une voiture possède un moteur et demande à this.engine.start() d’effectuer un travail. Le simple partage d’une fonction utilitaire ne justifie pas de dire qu’une classe sans lien est une sorte d’une autre. Un mixin copie un groupe de méthodes sur un prototype, par exemple avec Object.assign(Rectangle.prototype, serializable). De longues chaînes de classes parentes peuvent rendre les modifications difficiles à suivre.

Les classes intégrées peuvent aussi être étendues. Un constructeur ValidationError extends Error appelle super(message), définit this.name = "ValidationError" et peut stocker this.field = field. Un bloc catch peut utiliser err instanceof ValidationError pour traiter cet échec différemment et lire le message hérité.

Points clés

  • Utilise extends pour une relation « est un » et la composition pour une relation « possède un ».
  • Appelle super(...) avec les arguments nécessaires à la classe parente avant d’utiliser this.
  • Une méthode redéfinie peut réutiliser le comportement de la classe parente avec super.methodName().
  • Le polymorphisme permet à un même appel de méthode de fonctionner avec des classes apparentées.

1.4 Suis la recherche des propriétés dans les prototypes

Un objet possède un lien caché vers un autre objet, son prototype, ou vers null. La lecture d’une propriété absente suit ce lien. JavaScript poursuit la recherche jusqu’à trouver la propriété ou à atteindre null ; une recherche infructueuse renvoie undefined.

Distingue les valeurs stockées et héritées
const defaults = { theme: "light", fontSize: 16 };
const settings = Object.create(defaults);
settings.fontSize = 18;
settings.theme;                   // "light"
settings.fontSize;                // 18
defaults.fontSize;                // 16
Object.hasOwn(settings, "theme"); // false
"theme" in settings;              // true
Object.keys(settings);            // ["fontSize"]

Object.create(defaults) crée un objet vide dont le prototype est defaults. L’affectation à fontSize crée une propriété propre qui masque la valeur héritée. Elle laisse defaults.fontSize inchangé. Après delete settings.fontSize, la recherche atteint de nouveau la valeur héritée 16.

VérificationPropriétés prises en compte
Object.hasOwn(obj, key)Propriétés propres, énumérables ou non
Object.keys(obj)Clés de type chaîne propres et énumérables
key in objPropriétés propres et héritées, énumérables ou non
for...inClés de type chaîne énumérables, y compris héritées

Une propriété propre absente peut néanmoins exister dans la chaîne. Les méthodes de classe ne sont pas énumérables, donc for...in ne les répertorie normalement pas. Utilise Object.getPrototypeOf(settings) pour lire son prototype. Privilégie ces méthodes de Object à l’ancien accesseur __proto__.

Observe comment les classes partagent les méthodes

Pour une instance de rectangle r, Object.getPrototypeOf(r) === Rectangle.prototype est vrai. Sa largeur est une propriété propre, tandis que area est normalement stockée sur Rectangle.prototype. Object.hasOwn(r, "area") est faux même si r.area() fonctionne. Un champ contenant une fonction fléchée est différent : il crée sur chaque instance une propriété propre contenant une fonction.

Une méthode héritée reçoit toujours comme this l’objet placé avant le point. La méthode d’aire partagée peut donc lire des dimensions différentes pour chaque rectangle sans qu’une méthode distincte soit stockée sur chaque objet.

Pour la hiérarchie des formes, la recherche suit ce chemin :

circle -> Circle.prototype -> Shape.prototype
       -> Object.prototype -> null

La méthode d’aire du cercle est trouvée en premier. Sa description vient de Shape.prototype, et toString peut venir de Object.prototype. La présence de Shape.prototype dans la chaîne explique aussi pourquoi circle instanceof Shape est vrai.

Le nom Rectangle.prototype désigne le prototype donné aux instances de rectangle. Il ne désigne pas le prototype caché de la fonction Rectangle elle-même ; pour cette classe, il s’agit de Shape lorsqu’elle étend Shape, ou de Function.prototype pour une classe sans superclasse.

Reconnais l’ancien code utilisant des constructeurs
function Rectangle(width, height) {
  this.width = width;
  this.height = height;
}
Rectangle.prototype.area = function () {
  return this.width * this.height;
};

Les fonctions constructeurs utilisent la même structure de base reliant l’instance à son prototype. La syntaxe des classes ajoute des règles : new est obligatoire, le corps s’exécute en mode strict, les méthodes ne sont pas énumérables et les membres privés sont disponibles. typeof Rectangle vaut "function" dans les deux formes.

Les tableaux trouvent map sur Array.prototype ; les méthodes de chaînes viennent de String.prototype. Évite d’ajouter des méthodes personnalisées aux prototypes intégrés : des bibliothèques et de futures normes peuvent utiliser les mêmes noms avec des comportements différents. L’utilisation existante de flatten par une bibliothèque a contribué au choix du nom flat pour la méthode de tableau standard.

Une affectation à une propriété de données ordinaire crée ou modifie une propriété propre, mais un accesseur en écriture hérité peut intercepter l’affectation. Modifier le prototype d’un objet existant avec Object.setPrototypeOf est autorisé, mais peut nuire aux performances ; choisis le prototype lors de la création de l’objet.

Points clés

  • La lecture d’une propriété la recherche dans l’objet, puis dans ses prototypes, jusqu’à atteindre null.
  • Une propriété propre peut masquer une valeur héritée sans modifier le prototype.
  • Le fait qu’une propriété soit propre et le fait qu’elle soit énumérable sont deux questions distinctes.
  • Les méthodes de classe ordinaires se trouvent sur le prototype des instances et partagent leur comportement.
  • Une méthode héritée utilise l’instance receveuse comme this.
  • Les fonctions constructeurs et les classes reposent sur le même mécanisme de prototypes.
  • Laisse les prototypes intégrés inchangés pour éviter les conflits de noms et de comportements.
2

Relie les fichiers avec des modules ES

Les modules permettent à un programme de dépasser le cadre d’un seul script tout en gardant chaque fichier compréhensible. Les exportations décrivent ce qu’un fichier propose et les importations montrent ce dont il a besoin. Découvre comment fonctionne ce lien, comment les navigateurs et Node.js chargent les modules et comment ne charger une fonctionnalité que lorsqu’elle est demandée. Des frontières claires entre les données, le stockage et les mises à jour de la page facilitent aussi les tests et aident à prévenir les dépendances circulaires.

2.1 Exporte des fonctionnalités et importe leurs liaisons

Un module ES possède sa propre portée. Ses déclarations de niveau supérieur restent dans le fichier, sauf si elles sont exportées. Les fichiers importateurs demandent des fonctionnalités précises, ce qui rend les dépendances visibles sans tout placer dans des variables globales.

Fais correspondre la forme d’exportation
// geometry.js
export const round2 = (n) => Math.round(n * 100) / 100;
export function circleArea(r) {
  return Math.PI * r * r;
}

// shapes.js
import { circleArea, round2 } from "./geometry.js";
export default class Circle {
  constructor(r) { this.r = r; }
  area() { return round2(circleArea(this.r)); }
}

// main.js
import Circle from "./shapes.js";
console.log(new Circle(3).area()); // 28.27

Le module d’entrée importe une classe. Le module de la classe importe deux fonctions utilitaires. Pour un rayon de 3 cm, l’aire est d’environ 28,274 cm² ; la fonction d’arrondi produit 28,27. Le module d’entrée n’accède pas automatiquement aux fonctions utilitaires utilisées dans un autre module.

ExportationImportation correspondante
export const MAX = 30;import { MAX } from "./limits.js";
export default class Circle {}import Circle from "./shapes.js";
Une exportation par défaut et l’exportation nommée round2import Circle, { round2 } from "./shapes.js";

Un module peut avoir de nombreuses exportations nommées, mais au plus une exportation par défaut. Les importations nommées utilisent le nom exporté entre accolades ; le nom local d’une importation par défaut est choisi par le fichier importateur. Écrire import { Circle } ne demande pas l’exportation par défaut, même lorsque la classe exportée se nomme Circle.

Renomme, regroupe et réexporte

import { circleArea as areaOfCircle } from "./geometry.js"; donne à une fonctionnalité importée un nom local différent. export { circleArea as area }; change son nom à l’exportation. Une liste d’exportation peut aussi exposer des déclarations faites plus haut dans le fichier.

import * as geometry from "./geometry.js"; crée un objet d’espace de noms de module. Appelle geometry.circleArea(3). Un espace de noms inclut une exportation par défaut sous la propriété default si le module en possède une.

Un fichier peut regrouper les exportations d’autres fichiers : export { circleArea } from "./geometry.js"; transmet une exportation nommée. export * from "./geometry.js"; transmet les exportations nommées, mais pas l’exportation par défaut de ce module.

Comprends l’évaluation partagée et les liaisons dynamiques

Les modules s’exécutent en mode strict et leur this au niveau supérieur vaut undefined. Les dépendances sont évaluées avant le corps propre au module importateur. Importer le même module résolu depuis plusieurs fichiers réutilise un seul module évalué et son état.

Supposons qu’un module exporte let count = 0 et que increment() le modifie. Après l’appel de increment() par un fichier importateur, son count importé vaut 1. Les importations sont des liaisons dynamiques, pas des copies instantanées. Le fichier importateur ne peut pas réaffecter la liaison elle-même. Si une exportation est un objet, il reste possible de modifier une de ses propriétés et les autres fichiers importateurs voient cette modification.

Place les déclarations d’importation statique au niveau supérieur du module. Une importation statique dans un if ou une fonction est une erreur de syntaxe ; import() dynamique permet un chargement ultérieur. Inclus .js dans les chemins relatifs des modules ES pour le navigateur et Node.js : ces systèmes de chargement n’ajoutent pas l’extension. Une erreur de chemin ou une confusion entre exportations nommées et par défaut empêche le chargement du module : corrige donc l’importation avant de chercher un bogue dans le code censé s’exécuter ensuite.

Points clés

  • Les modules gardent locales les déclarations de niveau supérieur, sauf si elles sont exportées.
  • Les importations nommées utilisent des accolades ; une importation par défaut n’en utilise pas.
  • Un espace de noms regroupe les exportations, tandis que les réexportations transmettent l’interface d’un module.
  • Les importations sont des liaisons dynamiques en lecture seule vers l’état partagé d’un module.
  • Les importations statiques se placent au niveau supérieur et les chemins relatifs des modules ES nécessitent une extension.

2.2 Charge des modules dans les navigateurs et dans Node.js

La même syntaxe de modules ES s’exécute dans un navigateur et dans Node.js. Chaque environnement doit néanmoins savoir qu’un fichier est un module et possède sa propre façon de résoudre les chemins demandés.

Démarre un module dans le navigateur
<script type="module" src="main.js"></script>

Charge uniquement le module d’entrée avec une balise script. Ses importations récupèrent automatiquement les autres fichiers. Les scripts de module sans async sont différés : ils s’exécutent après l’analyse du HTML, dans l’ordre du document. Les éléments de la page auxquels ils accèdent sont alors disponibles.

Sers le dossier sur HTTP avec un serveur local, comme python3 -m http.server ou npx serve, puis ouvre son adresse localhost. Ouvrir le HTML depuis le disque fait généralement échouer les requêtes de modules en raison des règles de sécurité du navigateur. Le serveur doit aussi renvoyer le JavaScript avec un type MIME adapté, comme text/javascript.

Les déclarations d’un module ne deviennent pas globales. Un gestionnaire en ligne comme onclick="save()" ne peut pas trouver une fonction locale à un module. Attache plutôt le gestionnaire depuis le JavaScript :

const button = document.querySelector("#save");
function save() { console.log("Saved"); }
button.addEventListener("click", save);
Résous les chemins et les noms de paquets

Le spécificateur de module est la chaîne qui nomme le module. ./geometry.js est relatif au fichier importateur ; ../geometry.js remonte d’un dossier. Un chemin qui commence par / part de la racine du site web, tandis qu’une URL HTTPS complète indique son emplacement entier.

Un nom nu comme "date-fns" n’a pas de préfixe de chemin. Un navigateur ne peut pas le rechercher dans node_modules. Une carte d’importation placée avant les scripts de module associe un nom nu à une URL. Un serveur de développement ou un bundler peut à la place résoudre les paquets installés et les préparer pour le navigateur. Installer un paquet ne modifie pas à lui seul le système de chargement du navigateur.

Explicite le format de module de Node.js
Fichier ou réglageFormat dans Node.js
.mjsModule ES
.cjsCommonJS
.js avec "type": "module"Module ES
.js avec "type": "commonjs"CommonJS

Node.js lit type dans le fichier package.json parent le plus proche. Sans type explicite, les versions actuelles peuvent détecter la syntaxe des modules ES dans un fichier .js autrement ambigu. Définis "type": "module" dans un nouveau projet de modules ES afin que les outils s’accordent sur le format voulu. Les extensions .mjs et .cjs prévalent sur ce réglage.

Avec les trois fichiers de l’exemple du cercle et { "type": "module" }, node main.js affiche 28.27. Les mêmes fichiers fonctionnent avec un script de module dans le navigateur servi sur HTTP.

Reconnais CommonJS et les modules intégrés

CommonJS est l’ancien système de modules de Node.js. Il utilise require() pour charger de manière synchrone et module.exports pour fournir des valeurs. Un module ES peut importer module.exports d’un paquet CommonJS comme exportation par défaut. Les versions actuelles de Node.js peuvent aussi charger avec require des graphes de modules ES synchrones ; un await au niveau supérieur dans ce graphe empêche le chargement synchrone.

Dans un module ES, utilise import { readFile } from "node:fs/promises"; pour un module intégré de Node.js. require, module et __dirname sont des variables CommonJS, pas des variables globales de module ES. import.meta.url donne l’URL du module ; les versions récentes de Node.js fournissent aussi import.meta.dirname pour les modules correspondant à des fichiers locaux.

Si une instruction d’importation est rejetée parce qu’elle se trouve hors d’un module, examine le réglage de chargement : type="module" dans le HTML du navigateur, ou le type du paquet ou l’extension dans Node.js.

Points clés

  • Un module d’entrée dans le navigateur utilise type="module" et son exécution est normalement différée.
  • Utilise un serveur local et attache les gestionnaires d’événements depuis le module.
  • Les navigateurs ont besoin d’une carte d’importation ou d’outils de compilation pour résoudre les noms nus des paquets.
  • Node.js utilise les extensions de fichiers et le champ type du paquet le plus proche.
  • CommonJS utilise require et module.exports ; les modules ES utilisent import et export.

2.3 Charge les fonctionnalités à la demande et sépare les responsabilités

Une importation statique déclare une dépendance nécessaire au chargement d’un module. L’importation dynamique est une expression : elle commence le chargement lorsque l’exécution l’atteint et renvoie une promesse. Utilise-la pour une fonctionnalité dont de nombreuses visites n’ont jamais besoin.

Attends l’objet d’espace de noms
const button = document.querySelector("#show-chart");
button.addEventListener("click", async () => {
  try {
    const { drawChart } = await import("./chart.js");
    drawChart(measurements);
  } catch (err) {
    console.error("Could not load the chart module", err);
  }
});

Ici, measurements représente les données collectées par la page. Le premier clic charge le module de graphique et appelle sa fonction exportée. Les clics suivants réutilisent le module évalué. La promesse peut être rejetée en cas d’erreur de chargement ou d’évaluation : le gestionnaire intercepte donc cette erreur.

import("./chart.js").drawChart tente de lire une propriété sur la promesse, pas sur le module chargé. Attends la promesse ou utilise .then. Pour une exportation par défaut, accède à la propriété default de l’espace de noms : const { default: Chart } = await import("./chart.js");. Contrairement à une déclaration statique, cette expression peut se trouver dans une fonction ou une condition, et son chemin peut être calculé à l’exécution.

Attends pendant l’initialisation du module

Un module ES peut utiliser await au niveau supérieur, hors d’une fonction :

const response = await fetch("./config.json");
export const config = await response.json();

Les modules qui dépendent de celui-ci attendent la fin de son évaluation avant d’exécuter leur propre corps. Les modules indépendants peuvent continuer. Une requête de configuration lente retarde donc les modules qui en dépendent, mais pas nécessairement toutes les parties du programme. Les scripts classiques et CommonJS n’autorisent pas await au niveau supérieur ; utilise cette fonctionnalité du module pour les initialisations dont les modules dépendants ont réellement besoin en premier.

Donne à chaque module un rôle clair

Une application de tâches peut utiliser ces séparations :

ModuleResponsabilité
todo.jsExporter la classe Todo
storage.jsCharger et enregistrer les données avec localStorage
ui.jsAfficher la liste dans la page
main.jsRelier les modules et les gestionnaires d’événements

Les modules de données et de stockage n’importent pas l’interface utilisateur. Ils peuvent être testés et réutilisés sans créer d’éléments de page. Garder le calcul et le stockage hors des gestionnaires d’événements facilite aussi la localisation des erreurs.

L’état privé de niveau supérieur est partagé entre les fichiers importateurs. Dans let nextId = 1; export function createId() { return nextId++; }, la variable reste privée tandis que la fonction expose un accès contrôlé. Deux fichiers importateurs qui l’appellent chacun une fois obtiennent 1 et 2, et non deux compteurs distincts commençant à 1.

Contrôle le travail effectué à l’importation

import "./setup.js"; est une importation pour ses effets de bord : elle charge et évalue le module sans demander de noms locaux. Les effets de bord peuvent être utiles à l’initialisation, mais un module réutilisable est plus facile à tester lorsque son niveau supérieur définit des fonctionnalités et que ses fonctions démarrent explicitement le travail.

Un fichier d’index ou fichier barrel regroupe des réexportations. Il peut simplifier une interface, mais un fichier barrel volumineux peut introduire du code supplémentaire et masquer un cycle. Une dépendance circulaire apparaît lorsque des modules dépendent les uns des autres, directement ou par l’intermédiaire d’autres modules. Un cycle peut fonctionner, mais lire une liaison avant que le module qui l’exporte l’ait initialisée provoque une ReferenceError. Déplace les définitions partagées dans un troisième module importé par les deux côtés pour supprimer ce cycle de dépendance.

Points clés

  • import() renvoie une promesse dont le résultat sera un espace de noms de module et peut s’exécuter dans une fonction.
  • Attends le chargement dynamique et gère les promesses rejetées.
  • Await au niveau supérieur retarde l’évaluation des modules dépendants.
  • Sépare les données, le stockage, le rendu et la connexion des événements dans des modules ciblés.
  • Un module évalué unique peut contenir un état privé partagé par tous les fichiers qui l’importent.
  • Déplace les définitions partagées dans un troisième module pour rompre une dépendance circulaire.
3

Exécute un projet reproductible avec npm

Un projet a besoin d’une description claire de ses commandes et des paquets dont il dépend. npm conserve ces informations dans des fichiers de paquets et installe le code qu’ils décrivent. Apprends à lire les scripts avant de les exécuter, à distinguer les outils de développement des dépendances du produit et à utiliser les plages de versions avec un fichier de verrouillage. Ces choix permettent à un autre ordinateur de recréer le projet sans copier un dossier de paquets installés.

3.1 Décris et exécute un projet npm

npm est le gestionnaire de paquets fourni avec Node.js. Ce nom désigne à la fois un outil en ligne de commande et son registre public de paquets. Un paquet est un dossier décrit par package.json ; la racine d’un projet est le dossier qui contient ce fichier.

Crée la description du projet

Exécute node -v et npm -v pour vérifier les outils installés. Place-toi dans le dossier prévu pour le projet avant d’exécuter npm init. La commande interactive pose des questions ; npm init -y accepte les valeurs par défaut. Modifie ensuite le fichier pour décrire le projet.

{
  "name": "shape-lab",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "start": "node src/main.js",
    "test": "node --test",
    "lint": "eslint ."
  },
  "dependencies": {},
  "devDependencies": {}
}

Il s’agit de JSON, pas d’un littéral d’objet JavaScript. Les clés et les chaînes utilisent des guillemets doubles. Les commentaires et les virgules finales sont interdits. Une erreur d’analyse syntaxique peut arrêter npm avant qu’il n’exécute une commande.

Le name est en minuscules et utilisable dans une URL ; les noms des paquets publiés comportent au maximum 214 caractères. version décrit ce projet, pas sa version de Node.js. private: true empêche une publication accidentelle sur npm. type: "module" indique à Node.js de charger les fichiers .js du paquet comme des modules ES.

Les paquets publiés peuvent utiliser main et exports pour définir des points d’entrée destinés à leurs utilisateurs. Une entrée facultative engines, comme { "node": ">=22" }, indique les versions de Node.js prises en charge. Lis ces exigences lorsqu’un projet échoue sur une installation plus ancienne.

Utilise les scripts comme menu des tâches

npm run énumère les scripts disponibles. Dans cet exemple, npm run lint exécute eslint ., npm start exécute l’application et npm test exécute l’exécuteur de tests. start et test disposent de ces formes courtes ; les autres noms de tâches utilisent normalement npm run.

npm ajoute temporairement le répertoire node_modules/.bin du projet au chemin de recherche des commandes. Un outil installé localement peut donc être nommé directement dans un script. Toutes les personnes qui utilisent le projet exécutent le même outil enregistré au lieu de dépendre d’une installation globale.

Les arguments supplémentaires suivent -- : npm run lint -- --fix transmet --fix à ESLint. Le script donne un nom stable à la tâche même si l’équipe change l’outil utilisé derrière celle-ci. Commence par le champ scripts pour apprendre à travailler sur un projet inconnu.

Lis les numéros de version

Le versionnement sémantique utilise MAJEURE.MINEURE.CORRECTIF. À partir de 2.4.1, une correction de bogue compatible donne 2.4.2 ; une fonctionnalité compatible donne 2.5.0 ; un changement incompatible donne 3.0.0. Une mise à niveau majeure peut nécessiter des modifications du code qui utilise le paquet. Avant 1.0.0, un projet est en début de développement et les versions publiées peuvent changer plus librement.

Exécute occasionnellement une commande de paquet

npx serve exécute la commande installée si elle est disponible localement. Sinon, npx peut proposer de télécharger temporairement le paquet et de l’exécuter. C’est utile pour un outil qui n’a pas besoin de devenir une dépendance permanente du projet. Vérifie le nom exact du paquet et la fiabilité du code avant de l’installer ou de l’exécuter : les commandes de paquets et les scripts d’installation peuvent s’exécuter avec tes autorisations.

Une commande exécutée dans le mauvais dossier peut échouer parce que package.json manque, ou une installation peut créer des fichiers de paquets à un endroit non prévu. Vérifie d’abord le dossier courant. Garde les scripts compréhensibles et évite les astuces de commande propres à un système d’exploitation lorsque le projet doit fonctionner sur plusieurs systèmes.

Points clés

  • package.json décrit le projet, les scripts et les dépendances en JSON valide.
  • private: true empêche la publication sur npm ; type définit le format de module de Node.js.
  • Utilise des scripts npm pour exécuter de façon cohérente les outils installés localement.
  • Les versions sémantiques distinguent les changements incompatibles, les fonctionnalités compatibles et les correctifs.
  • npx peut exécuter une commande locale ou en télécharger une temporairement.

3.2 Installe et mets à jour les bonnes versions des paquets

Une dépendance est du code dont un projet dépend. npm enregistre les dépendances directes dans package.json, installe les paquets dans node_modules et enregistre l’arbre exact des dépendances installées dans package-lock.json.

Sépare le code du produit des outils de développement

npm install date-fns ajoute un paquet d’exécution à dependencies. npm install --save-dev eslint ajoute un outil de développement à devDependencies ; -D est la forme courte. Les linters, formateurs de code, exécuteurs de tests, bundlers et TypeScript appartiennent normalement à la liste de développement.

Lorsqu’un autre projet installe un paquet publié, npm installe les dépendances de ce paquet, mais pas ses dépendances de développement. Une application de navigateur peut tout de même regrouper les dépendances d’exécution dans ses fichiers finaux, même si l’outil de compilation lui-même est une devDependency.

npm install sans nom de paquet installe les dépendances indiquées pour le projet. npm uninstall <package> supprime un paquet et son entrée. Après l’installation de date-fns, Node.js et les outils de compilation peuvent résoudre import { format } from "date-fns";. Un navigateur seul a toujours besoin d’un mécanisme de résolution, comme une carte d’importation ou un serveur de développement.

Lis la plage autorisée
EntréeVersions stables autorisées
^4.17.21Au moins 4.17.21, inférieure à 5.0.0
~4.17.21Au moins 4.17.21, inférieure à 4.18.0
4.17.21Exactement 4.17.21
^0.3.1Au moins 0.3.1, inférieure à 0.4.0

L’accent circonflexe est la valeur par défaut habituelle de npm. Pour les versions à partir de 1.0.0, il autorise les mises à jour mineures et les correctifs compatibles. En dessous de 1.0.0, il est plus strict. Pour ^2.3.0, 2.3.5 et 2.9.0 conviennent ; 2.2.9 est trop ancienne et 3.0.0 franchit la limite de version majeure.

Une plage autorisée ne désigne pas une version installée précise. Le fichier de verrouillage le fait, y compris pour les dépendances transitives, c’est-à-dire les paquets dont les paquets choisis ont besoin.

Recrée une installation

Partage package.json et package-lock.json avec le projet. Laisse npm gérer le fichier de verrouillage. Le dossier généré node_modules peut être reconstruit et n’est pas le fichier à partager.

Utilise npm install pendant le développement, lorsque les enregistrements des dépendances peuvent changer. Utilise npm ci pour une installation propre et reproductible : la commande exige le fichier de verrouillage, supprime le dossier node_modules existant, installe l’arbre verrouillé et ne réécrit aucun des deux fichiers de paquets. Elle échoue si le fichier de paquet et le fichier de verrouillage ne correspondent pas. Corrige cet écart volontairement pendant le développement ; supprimer le fichier de verrouillage peut modifier silencieusement de nombreuses versions.

Mets à jour pour une raison précise

npm outdated compare les versions actuelles, souhaitées et les plus récentes. La version souhaitée est la plus récente autorisée par la plage déclarée ; la plus récente peut être une version majeure hors de cette plage. npm update met à jour dans les plages autorisées et enregistre l’arbre obtenu. Pour franchir volontairement une limite de version majeure, lis le journal des modifications, exécute npm install <package>@latest et vérifie le projet avec ses tests.

Installe les outils du projet localement afin que leurs versions soient enregistrées. Avant d’ajouter une dépendance, vérifie sa maintenance, son adoption, sa licence et si une fonctionnalité intégrée résout déjà le problème. structuredClone() répond aux besoins de copie profonde qu’il prend en charge ; Intl.DateTimeFormat met en forme les dates sans paquet de gestion des dates.

npm audit signale les vulnérabilités connues des versions installées. Lis le rapport pour comprendre le code concerné et son utilisation. npm audit fix peut appliquer des correctifs compatibles, mais ne prouve pas que toutes les vulnérabilités sont résolues ni qu’une mise à jour préserve le comportement du projet.

Points clés

  • Utilise dependencies pour le code d’exécution et devDependencies pour les outils de développement et de compilation.
  • Les plages de versions autorisent certaines versions ; le fichier de verrouillage enregistre les versions exactes installées.
  • Partage les deux fichiers de paquets et reconstruis node_modules.
  • npm ci installe les versions du fichier de verrouillage sans le modifier et rejette les fichiers de paquets qui ne correspondent pas.
  • npm update reste dans les plages déclarées ; les mises à niveau majeures nécessitent un choix délibéré.
  • Lis les rapports d’audit et vérifie le comportement après les mises à jour des dépendances.
4

Vérifie et prépare le code avec des outils de développement

Les différents outils répondent à différentes questions sur un projet. Un linter recherche du code suspect, un formateur le met en forme, des tests vérifient son comportement et une compilation prépare les fichiers du navigateur pour leur publication. Un serveur de développement accélère le cycle de modification. Apprends ce que chaque résultat t’indique et ce qu’il ne vérifie pas, afin de ne pas prendre la réussite d’une commande de mise en forme ou l’affichage d’une page de développement pour une preuve que toute l’application fonctionne.

4.1 Repère les problèmes du code et mets-le en forme de façon cohérente

Un linter lit le code source sans l’exécuter et signale les bogues probables ou les constructions risquées. Un formateur de code réécrit la présentation de manière cohérente. ESLint et Prettier sont souvent utilisés ensemble, car ces rôles résolvent des problèmes différents.

Configure les vérifications

npm init @eslint/config@latest pose des questions sur le projet, installe des paquets de développement et crée un fichier de configuration. ESLint utilise actuellement la configuration à plat, généralement dans eslint.config.js.

import js from "@eslint/js";
import globals from "globals";

export default [
  js.configs.recommended,
  {
    languageOptions: { globals: globals.browser },
    rules: {
      eqeqeq: "error",
      "no-unused-vars": "warn",
    },
  },
];

La configuration recommandée active des règles de détection des bogues. Les variables globales du navigateur indiquent à ESLint que des noms comme document existent. Cela évite de considérer une fonctionnalité réelle de l’environnement comme un nom non défini.

Les niveaux de sévérité des règles sont "off", "warn" et "error", également écrits 0, 1 et 2. Les erreurs produisent un code de sortie indiquant un échec ; les avertissements seuls ne font pas échouer la commande par défaut. Un avertissement reste une information à lire, même si le script se termine avec succès.

Lis un rapport du linter
function total(items) {
  let sum = 0;
  let unused = 5;
  for (const item of items) {
    if (item.quantity == "2") sum += item.price;
  }
  return summ;
}

Avec la configuration ci-dessus, cinq problèmes sont signalés. total n’est jamais utilisée. sum est mise à jour, mais sa valeur n’est jamais utilisée en dehors de ces mises à jour. unused n’est pas utilisée. La règle eqeqeq signale ==, et no-undef repère la faute de frappe summ. L’appel de cette fonction échouerait sur ce nom non défini, mais le linter peut le trouver sans l’appeler.

Commence par le nom et l’emplacement de la règle dans le rapport. Corrige le comportement voulu, puis relance la commande. npm run lint -- --fix demande des corrections automatiques sûres lorsque le projet possède un script lint. L’outil ne peut pas décider de la bonne logique métier pour chaque avertissement. Ne désactive une règle sur une ligne que si tu as une raison, et indique cette raison à côté du commentaire.

Confie la mise en forme à un seul formateur
npm install --save-dev --save-exact prettier
npx prettier . --write
npx prettier . --check

--write modifie les fichiers ; --check signale les différences de mise en forme sans les modifier. Avec les réglages par défaut, const point={x:1,y:2} devient const point = { x: 1, y: 2 };. Les options comme "singleQuote": true se placent dans .prettierrc.

OutilQuestion principale
ESLintCe code contient-il une construction signalée par une règle ?
PrettierLe code respecte-t-il la mise en forme choisie ?
Exécuteur de testsLe code produit-il le comportement attendu ?

Les règles recommandées d’ESLint n’imposent pas la mise en forme de Prettier : cette configuration évite donc les conflits de mise en forme. Si une autre configuration ESLint ajoute des règles de style incompatibles, eslint-config-prettier les désactive. L’exécution de deux formateurs concurrents peut modifier les fichiers dans un sens puis dans l’autre.

Ajoute des scripts lint et format pour faciliter la répétition des vérifications. Après configuration, les extensions de l’éditeur peuvent afficher des diagnostics pendant la saisie et mettre en forme à l’enregistrement. Les deux outils ignorent node_modules par défaut ; ajoute les résultats générés comme dist aux paramètres d’exclusion appropriés. Une fonction qui ne déclenche aucun avertissement du linter peut quand même calculer le périmètre alors qu’elle devrait calculer l’aire ; le comportement nécessite des tests.

Points clés

  • Un linter trouve les problèmes du code source prévus par sa configuration sans exécuter le programme.
  • Dans ESLint, le niveau erreur fait échouer la commande ; les avertissements ne la font pas échouer par défaut.
  • Prettier modifie la mise en forme avec --write et la vérifie avec --check.
  • Utilise des règles compatibles pour le linter et la mise en forme, ainsi que des tests pour le comportement.

4.2 Développe localement et prépare les fichiers pour le navigateur

Un navigateur peut charger directement quelques modules ES, mais les projets plus importants utilisent aussi des paquets installés et des fichiers qui nécessitent une transformation. Un serveur de développement prépare les fichiers pendant que tu les modifies. Un bundler suit les dépendances pour produire des fichiers adaptés à la publication.

Parcours le cycle Vite
npm create vite@latest shape-lab
cd shape-lab
npm install
npm run dev
npm run build
npm run preview

Choisis le modèle JavaScript Vanilla pour ce projet. Le générateur fournit des scripts de développement et de compilation. npm run dev affiche une adresse locale, souvent http://localhost:5173. Ouvre cette adresse pendant les modifications. Dans Vite, index.html est le point d’entrée et charge généralement /src/main.js avec un script de module.

Le serveur de développement résout les noms de paquets et transforme les fichiers selon les besoins. L’enregistrement d’un fichier déclenche une mise à jour. Le remplacement de modules à chaud, ou HMR, remplace un module modifié dans la page en cours d’exécution ; les mises à jour prises en charge peuvent préserver l’état au lieu d’imposer un rechargement complet.

npm run build écrit les résultats optimisés dans dist. npm run preview sert ces résultats localement afin que tu puisses vérifier la compilation de production réelle. La prévisualisation nécessite une compilation existante et n’en crée pas une nouvelle. Modifie les fichiers sources, car une nouvelle compilation remplace les résultats générés.

Comprends les changements apportés pour la production
Fonction de compilationRôle
RegroupementCombiner les modules en un plus petit nombre de fichiers pour le navigateur
Tree shakingSupprimer le code dont la compilation peut prouver qu’il est inutilisé
MinificationRéduire la taille en supprimant la mise en forme et en raccourcissant les noms
Empreintes du contenuChanger les noms des ressources lorsque leur contenu change, pour faciliter la mise en cache
Fractionnement du codeGarder une partie du code dans des fragments distincts qui peuvent être chargés plus tard

Par exemple, un module de fonctions utilitaires peut exporter à la fois formatArea et formatVolume. Si seule formatArea est utilisée et que la suppression de l’autre code est sûre, le tree shaking peut omettre formatVolume. Les importations et exportations statiques rendent les dépendances visibles. Les effets de bord d’un module au niveau supérieur peuvent devoir être conservés même si aucune de ses exportations n’est utilisée.

Un import() dynamique donne à l’outil de compilation un point de séparation pour un chargement ultérieur. Les outils de compilation peuvent créer des fragments distincts à cet endroit ; leur organisation dépend de la compilation, donc un module source ne devient pas toujours exactement un fichier de sortie.

Un nom comme assets/index-4f2a9c1b.js change avec son contenu, ce qui permet de conserver longtemps les fichiers dans le cache du navigateur sans servir un ancien fichier après une mise à jour. Une carte des sources relie les emplacements générés aux lignes du code source d’origine, ce qui facilite les traces de pile et le débogage lorsque les cartes sont disponibles.

Inclus les ressources et la configuration publique

Vite traite aussi les ressources : import "./style.css"; inclut des styles et import logoUrl from "./logo.png"; fournit l’URL finale de l’image. La compilation peut mettre ces références à jour pour les faire correspondre aux noms de fichiers générés.

Lis les informations de mode avec import.meta.env.MODE. Ses valeurs par défaut sont "development" pour le développement et "production" pour une compilation ; un mode personnalisé peut utiliser un autre nom. Les valeurs d’environnement personnalisées commençant par VITE_ sont exposées au code du navigateur par défaut. Tout ce qui est envoyé au navigateur est public : garde les clés secrètes et les mots de passe sur un serveur, hors du code du navigateur et des variables d’environnement exposées.

Ne vérifie pas uniquement la page de développement. Compile et prévisualise avant la publication pour repérer les problèmes dans les résultats transformés et les chemins des ressources. Ouvrir dist/index.html directement depuis le disque ne reproduit pas la mise à disposition du site sur HTTP. Une petite page avec quelques modules simples peut n’avoir besoin que d’un serveur statique, sans outil de compilation complet.

Points clés

  • Un serveur de développement résout et transforme les fichiers pendant les modifications ; une compilation de production crée les fichiers à publier.
  • Le HMR peut remplacer le code modifié tout en conservant l’état de la page lorsque la mise à jour le permet.
  • Le tree shaking ne supprime du code que lorsque la compilation peut l’omettre sans risque.
  • Les empreintes du contenu facilitent la mise en cache et les cartes des sources relient les résultats au code source.
  • Compile d’abord, puis prévisualise localement les résultats générés.
  • Les bundles du navigateur et les valeurs d’environnement exposées sont publics.

4.3 Teste le comportement avec des assertions

Un test automatisé exécute du code avec des entrées connues et vérifie le résultat à l’aide d’assertions. Un test unitaire porte sur un petit élément, comme une fonction ou une méthode. L’exécuteur trouve les tests, les exécute, signale les échecs et termine avec un code indiquant un échec lorsqu’un test échoue.

Prépare, agis, vérifie

Prépare les entrées, agis en appelant le code et vérifie le résultat attendu. Un nom de test utile décrit le comportement. Pour une classe de rectangle dont le constructeur rejette un côté négatif :

import { test } from "node:test";
import assert from "node:assert/strict";
import { Rectangle } from "./rectangle.js";

test("area multiplies width by height", () => {
  assert.equal(new Rectangle(3, 4).area(), 12);
});
test("rejects a negative width", () => {
  assert.throws(() => new Rectangle(-1, 4), RangeError);
});

La première assertion vérifie que le résultat est de 12 cm², une valeur connue indépendamment du code. La seconde passe une fonction à assert.throws pour que l’assertion puisse observer l’erreur. La commande node --test trouve les fichiers dont le nom ressemble à rectangle.test.js ; le script de paquet "test": "node --test" permet d’utiliser npm test.

Le mode d’assertion strict utilise Object.is pour assert.equal, sans conversion implicite. assert.deepEqual compare le contenu des objets et des tableaux. Deux tableaux distincts contenant les mêmes valeurs ne sont pas le même objet : une comparaison stricte d’identité ne convient donc pas pour vérifier l’égalité de leurs contenus.

Utilise les mêmes principes dans Vitest
import { describe, it, expect } from "vitest";
import { Rectangle } from "./rectangle.js";

describe("Rectangle", () => {
  it("computes the area", () => {
    expect(new Rectangle(3, 4).area()).toBe(12);
  });
  it("rejects a negative width", () => {
    expect(() => new Rectangle(-1, 4)).toThrow(RangeError);
  });
});

Vitest utilise describe pour regrouper les tests et it pour les tests individuels. Exécute npx vitest pour surveiller les modifications ou npx vitest run pour une seule exécution. Jest propose un style similaire. Utilise toEqual pour les contenus et toBe pour l’identité ou les valeurs primitives.

Inclus les bornes et les limites numériques

Teste les bornes exactes d’un intervalle autorisé ainsi que les entrées juste à l’extérieur. Pour un thermostat qui accepte de 10 à 30 °C, il faut des tests qui acceptent 10 et 30, ainsi que des tests qui rejettent 9,5 et 30,5. Ajoute des vérifications distinctes pour les valeurs non numériques et non finies si l’interface les rejette. Les tests ne doivent pas dépendre d’un objet modifié par un test précédent ni de leur ordre d’exécution.

Le calcul en virgule flottante peut ne pas correspondre exactement à un nombre décimal écrit : 0.1 + 0.2 vaut 0.30000000000000004. Pour utiliser une tolérance adaptée, écris assert.ok(Math.abs(actual - expected) < 1e-9). Un cercle de rayon 3 a une aire d’environ 28,274333882 cm² ; toBeCloseTo(28.27, 2) de Vitest vérifie que la valeur est proche avec cette précision décimale. Choisis la tolérance selon ce que le test doit établir.

Tire des enseignements d’un échec

Lis le comportement nommé, les valeurs attendue et obtenue, ainsi que l’emplacement dans le code source. Détermine si l’erreur vient de l’implémentation ou du résultat attendu par le test. Dans le développement piloté par les tests, écris un test qui échoue, implémente juste assez pour le faire réussir, puis améliore le code en gardant les tests au vert.

Exporte la logique depuis les modules et passe les entrées comme arguments. Un gestionnaire d’événements peut alors recueillir les données de la page et appeler cette logique, au lieu de mêler les calculs aux opérations sur le DOM. Le code dépendant du DOM peut utiliser un navigateur simulé comme jsdom. Attends les opérations asynchrones dans un test asynchrone pour que le test ne se termine pas avant ses vérifications. Un test qui se contente de répéter la formule de l’implémentation peut répéter son bogue ; utilise le comportement attendu et des exemples indépendants.

Points clés

  • Les tests exécutent le code et utilisent des assertions pour vérifier un comportement attendu établi indépendamment.
  • Prépare les entrées, agis et vérifie un comportement, avec un nom de test utile.
  • Compare les contenus des tableaux ou objets distincts dont les contenus sont égaux.
  • Teste les bornes et les entrées invalides, et utilise des tolérances adaptées aux calculs en virgule flottante.
  • Attends les opérations asynchrones et garde les tests indépendants de leur ordre d’exécution.
5

Situe les types et les frameworks dans la méthode de travail

TypeScript et les frameworks front-end s’appuient sur les outils JavaScript déjà présentés. Les types aident un éditeur et un vérificateur à trouver les valeurs incompatibles avant l’exécution. Les composants aident à organiser les interfaces qui partagent et modifient des données. Aucun des deux ne dispense de comprendre les modules, les dépendances ou les tests. Utilise les scripts du projet pour voir comment ces éléments coopèrent, puis ajoute des outils lorsque le travail leur donne un rôle clair.

5.1 Comprends ce que TypeScript vérifie

TypeScript ajoute à JavaScript une syntaxe de types statiques. Un type décrit le genre de valeur attendu par le code. Le vérificateur utilise ces descriptions avant l’exécution du programme, ce qui peut révéler des erreurs avant qu’un utilisateur ne les rencontre.

Vérifie un appel avant son exécution
function area(width: number, height: number): number {
  return width * height;
}
area(3, "4"); // type error: the second argument is a string

Les deux paramètres doivent être des nombres. La valeur écrite "4" est une chaîne : le vérificateur signale donc l’incompatibilité. JavaScript ordinaire convertirait implicitement cette chaîne dans une multiplication : 3 * "4" donne 12. Avec une addition, 3 + "4" donne "34". Une erreur de type indique une incompatibilité dans les entrées prévues, même si JavaScript pourrait exécuter l’expression.

Une interface décrit la structure d’un objet :

interface Shape {
  name: string;
  area(): number;
}

Une classe déclarée avec implements Shape doit fournir les propriétés et méthodes indiquées avec des types compatibles. Le vérificateur peut aussi détecter les propriétés mal orthographiées, les nombres incorrects d’arguments et les valeurs potentiellement undefined lorsque la vérification stricte est activée.

Distingue la vérification de la suppression des types
Outil ou actionRôle
tscVérifie les types et produit normalement du JavaScript
tsc --noEmitVérifie les types sans écrire de fichiers en sortie
Transformation TypeScript de ViteSupprime la syntaxe de type pour l’exécution
Effacement des types de Node.jsExécute le TypeScript pris en charge dont les types peuvent être effacés, après leur suppression

Les réglages du projet TypeScript se trouvent dans tsconfig.json. Une compilation Vite ne démontre pas à elle seule que tous les types sont corrects. Les projets exécutent généralement tsc --noEmit séparément. Les versions actuelles de Node.js peuvent exécuter directement les fichiers .ts pris en charge, mais leur effacement des types ne vérifie pas non plus ces derniers.

Garde des vérifications à l’exécution aux points d’entrée des données

Les annotations de type sont supprimées avant l’exécution. Déclarer le type attendu des données provenant de fetch() ou de JSON.parse() ne vérifie pas leur valeur réelle. Vérifie les données externes dans le code en cours d’exécution avant de t’y fier. Un serveur peut envoyer une chaîne même si une déclaration de type indique qu’un champ est numérique.

Les mots-clés private et readonly de TypeScript sont des restrictions du vérificateur ; ils n’assurent pas la confidentialité à l’exécution offerte par # en JavaScript. Les champs privés JavaScript restent protégés pendant l’exécution du programme. TypeScript n’accélère pas non plus un programme et ne prouve pas que ses calculs sont corrects.

Le type any désactive des vérifications utiles pour une valeur. Il peut faire taire une erreur tout en laissant subsister l’erreur d’origine. Corriger une hypothèse erronée ou ajouter une véritable vérification des données donne de meilleures informations au vérificateur.

Adopte-le par étapes abordables

Un fichier JavaScript peut commencer par // @ts-check et utiliser JSDoc, par exemple /** @param {number} width */, pour bénéficier de vérifications dans les éditeurs compatibles sans devenir un fichier .ts. Un projet peut ensuite renommer les fichiers un par un. Les bibliothèques peuvent fournir des définitions de types .d.ts ; les définitions communautaires sont souvent distribuées sous @types/....

Les projets plus importants et durables gagnent des interfaces plus claires, des remaniements plus sûrs et une meilleure complétion dans l’éditeur. Un petit script ne justifie peut-être pas encore une étape de compilation et une syntaxe supplémentaires. Les tests restent utiles dans les deux cas : une fonction d’aire correctement typée peut quand même renvoyer le mauvais résultat numérique.

Points clés

  • TypeScript vérifie les types de valeurs attendus avant l’exécution.
  • La suppression de la syntaxe de type est distincte de la vérification des types.
  • Les déclarations de type ne valident pas les données externes pendant l’exécution du programme.
  • La confidentialité assurée par # en JavaScript est imposée à l’exécution ; private de TypeScript est vérifié statiquement.
  • La vérification JSDoc permet une adoption progressive avant la conversion des fichiers en TypeScript.

5.2 Combine les outils selon les besoins du projet

Une bibliothèque fournit du code que ton programme appelle. Un framework fournit une structure d’application et appelle ton code aux moments appropriés. Ce changement de contrôle aide à coordonner des interfaces plus importantes, mais repose toujours sur JavaScript, les modules et une chaîne d’outils de projet.

Organise une interface en composants

React, Vue, Svelte et Angular organisent les interfaces utilisateur avec des composants : des éléments réutilisables comme une barre de navigation ou une tâche à faire. Un composant combine du balisage et un comportement, souvent avec des styles. Lorsque son état change, le système d’interface utilisateur coordonne les mises à jour correspondantes de la page.

Les méta-frameworks comme Next.js, Nuxt, SvelteKit et Astro ajoutent une infrastructure plus complète, comprenant le routage, le rendu sur le serveur et la prise en charge de la compilation. Leurs fonctionnalités exactes diffèrent. Connaître les fonctions JavaScript, les événements, le code asynchrone et les limites entre modules aide à apprendre chacun d’eux.

Pour une page avec quelques fonctionnalités interactives indépendantes, du JavaScript ordinaire peut rester clair. Un framework devient utile lorsque de nombreuses vues doivent partager des données changeantes. Choisis-le pour ce besoin au lieu de supposer que chaque page nécessite la chaîne d’outils la plus complète.

Suis la coopération des outils

Les paquets des frameworks sont installés avec npm et importés comme modules. Les outils de compilation transforment des syntaxes comme JSX ou des fichiers propres à un framework. TypeScript peut vérifier les interfaces entre les parties. La vérification par un linter, la mise en forme et les tests gardent leurs rôles distincts quel que soit le choix d’interface utilisateur.

Commence un projet simple et ajoute les outils utilisés par l’équipe :

npm create vite@latest shape-lab
cd shape-lab
npm install
npm install --save-dev eslint @eslint/js globals prettier vitest

Un modèle Vite fournit les outils de développement et de compilation. L’installation de paquets supplémentaires ne les configure pas : ajoute la configuration ESLint, crée des tests et configure les extensions de l’éditeur pour vérifier et mettre en forme le code à l’enregistrement. Un champ de scripts peut fournir ces tâches :

{
  "dev": "vite",
  "build": "vite build",
  "preview": "vite preview",
  "lint": "eslint .",
  "format": "prettier . --write",
  "test": "vitest run"
}

Ces entrées se placent dans "scripts" dans package.json. Pendant les modifications, exécute npm run dev ; l’éditeur peut vérifier et mettre en forme les fichiers à mesure qu’ils changent. Avant de partager le travail, exécute npm test. Avant la publication, exécute npm run build et npm run preview. Le dossier dist compilé d’un site statique peut ensuite être envoyé à un hébergeur statique adapté.

Trouve le fichier qui contrôle une tâche
Fichier ou dossierRôle
package.jsonCommandes et plages de versions des dépendances directes
package-lock.jsonArbre exact des dépendances
node_modules/Paquets installés générés
eslint.config.jsRègles du linter et environnements
.prettierrcOptions de mise en forme
vite.config.jsOptions de développement et de compilation
tsconfig.jsonRéglages de vérification et de compilation TypeScript
dist/Résultats de compilation générés

Commence l’étude d’un projet inconnu par package.json : ses scripts révèlent comment le projet s’exécute et ses listes de dépendances indiquent les outils nécessaires à ces scripts. Les dossiers générés peuvent être recréés ; les réglages et les sources expliquent comment les recréer.

Apprends les nouveaux outils un par un afin que la cause d’une erreur reste reconnaissable. Utilise la documentation officielle de la version installée lorsque les commandes ou les réglages par défaut diffèrent, car les versions des outils et des frameworks changent plus souvent que la syntaxe de base de JavaScript.

Points clés

  • Une bibliothèque est appelée par ton code ; un framework appelle ton code dans sa structure.
  • Les composants coordonnent des éléments réutilisables de l’interface utilisateur et un état qui change.
  • Les projets utilisant un framework dépendent toujours des modules, des paquets, des compilations et des vérifications.
  • Les modèles et l’installation de paquets ne configurent pas automatiquement tous les outils supplémentaires.
  • Lis d’abord les scripts du paquet pour découvrir la méthode de travail d’un projet.
  • Ajoute des outils pour répondre à un besoin concret et consulte la documentation de la version installée.

Classes et modules JavaScript : exemples

5 Leçons Interactives

1

Construis une petite famille d’objets

18 étapes
Crée des instances, protège leur état, spécialise leur comportement et suis les méthodes partagées qui font fonctionner le modèle.
  1. 1
    IntroductionCommence par des objets qui ont besoin de comportements

    Un programme peut stocker de nombreux rectangles, mais chacun a aussi besoin d’opérations comme l’aire et le périmètre. Une classe permet à ces objets de partager les opérations tout en gardant leurs dimensions distinctes.

    Suis l’objet depuis sa création jusqu’à un appel de méthode. Ajoute ensuite un état protégé, distingue les valeurs au niveau de la classe et spécialise le comportement par héritage. Enfin, examine la chaîne de prototypes pour voir où se trouvent les méthodes partagées.

  2. 2
    ExempleInitialise une instance

    Le constructeur stocke des valeurs sur le nouvel objet. Ici, les dimensions sont en centimètres :

    class Rectangle {
      constructor(width, height) {
        this.width = width;
        this.height = height;
      }
      area() { return this.width * this.height; }
    }
    const a = new Rectangle(3, 4);
    

    new crée a et exécute le constructeur avec this qui le désigne. Les deux affectations donnent à a sa propre largeur et sa propre hauteur.

  3. 3
    ExempleAppelle un comportement partagé avec des données distinctes

    Ajoute const b = new Rectangle(5, 2);. Les deux objets peuvent appeler area, mais chaque appel lit les dimensions de l’objet receveur.

    a.area() multiplie 3 par 4 et renvoie 12 cm². b.area() multiplie 5 par 2 et renvoie 10 cm². L’affectation b.width = 8 ne modifie que b : son aire suivante est donc de 16 cm², tandis que celle de a reste à 12 cm².

    La méthode n’a pas besoin d’une copie distincte de son code pour chaque rectangle. Les données qu’elle lit proviennent de this.

  4. 4
    ConseilConserve l’objet dans une fonction de rappel

    Extraire une méthode d’un objet ne lui attache pas définitivement son objet receveur :

    const calculate = a.area;
    // calculate(); // this is undefined
    const calculateSafely = () => a.area();
    

    Les méthodes de classe s’exécutent en mode strict. L’appel détaché n’a pas d’objet avant le point, donc la lecture de this.width échoue. La fonction fléchée enveloppante conserve l’appel de méthode d’origine. a.area.bind(a) est une autre façon de produire une fonction de rappel liée à a.

  5. 5
    DéfiPrévois un deuxième appel

    Un nouveau Rectangle(6, 2) est affecté à tile. L’instruction tile.width = 7 s’exécute. Que renvoie tile.area() et pourquoi cela ne modifie-t-il pas un autre rectangle créé auparavant ?

    ---reveal---

    Elle renvoie 14 cm² : la méthode lit la largeur actuelle de l’objet receveur, 7 cm, et sa hauteur, 2 cm. Chaque instance stocke ses propres dimensions : modifier tile.width ne met donc pas à jour une autre instance. Le partage d’une méthode ne rend pas les champs d’instance partagés.

  6. 6
    ExplicationStocke l’état derrière un accesseur en écriture

    Un thermostat peut exposer target tout en stockant #target de façon privée. Un accesseur en lecture lit la valeur privée ; un accesseur en écriture vérifie une modification demandée.

    L’accesseur en écriture rejette les entrées non finies ou non numériques et les valeurs hors de l’intervalle de 10 à 30 °C avant d’effectuer l’affectation this.#target = value. Cet ordre compte : lever une exception avant l’affectation préserve la dernière consigne valide. Le nom de stockage distinct évite aussi que l’accesseur en écriture se rappelle sans cesse.

  7. 7
    ExempleSuis une modification acceptée et une modification rejetée

    Pars d’une consigne de thermostat de 20 °C. L’affectation de 22 passe les deux vérifications : l’accesseur en écriture stocke donc 22. L’affectation de 35 lève ensuite une RangeError ; la valeur stockée reste à 22.

    Number.isFinite(value) rejette aussi "22", NaN et l’infini. Les seules comparaisons aux bornes ne rejetteraient pas tous les types ou valeurs invalides. Le stockage privé contrôle l’accès direct, tandis que la validation contrôle ce que l’interface publique accepte.

  8. 8
    Point cléChoisis entre stockage sur la classe et sur l’instance

    Un champ déclaré avec static appartient à la classe. Lis la borne inférieure du thermostat avec Thermostat.MIN, tandis que t.target lit l’état d’une instance.

    Un compteur statique peut suivre le nombre d’objets construits. Un champ ordinaire est au contraire initialisé séparément sur chaque nouvel objet. Dans une méthode statique, this est la classe qui reçoit l’appel : il ne fournit donc pas la consigne ou les dimensions d’une instance.

  9. 9
    DéfiUtilise l’interface publique

    Une sous-classe de Thermostat doit augmenter sa consigne de 20 à 24 °C. La classe parente déclare #target et un accesseur en écriture public target qui valide les valeurs. Comment la sous-classe doit-elle demander la modification, et que produirait un accès direct avec this.#target ?

    ---reveal---

    Effectue l’affectation this.target = 24 pour que l’accesseur en écriture hérité valide et stocke la valeur. La sous-classe ne peut pas nommer directement le champ privé de la classe parente ; cette utilisation de #target est une erreur de syntaxe. Les accesseurs hérités s’exécutent toujours dans la classe qui a déclaré l’état privé.

  10. 10
    ExempleDonne une classe parente à des classes apparentées

    Un constructeur Shape stocke un nom et sa méthode describe() appelle this.area(). Un cercle spécialise le calcul :

    class Circle extends Shape {
      constructor(radius) {
        super("Circle");
        this.radius = radius;
      }
      area() { return Math.PI * this.radius ** 2; }
    }
    

    super initialise la partie parente avant l’utilisation de this.radius. Un cercle est une forme : la description héritée convient donc à son rôle.

  11. 11
    ExempleLaisse l’objet receveur choisir le calcul

    Avec un rayon de 2 cm, new Circle(2).describe() renvoie "Circle with area 12.57 cm²". La méthode de description est héritée, mais son appel à this.area() trouve la méthode redéfinie du cercle.

    Un rectangle peut hériter de cette même description et fournir une multiplication comme méthode d’aire. Une boucle qui appelle describe() sur les deux objets n’a pas besoin de branches distinctes pour le cercle et le rectangle. Cette interface commune avec des comportements différents est le polymorphisme.

  12. 12
    ExplicationÉtends une méthode de la classe parente

    Un carré peut appeler super(side, side) dans son constructeur pour donner des dimensions égales à sa classe parente rectangle. Une description redéfinie peut ensuite appeler super.describe() et ajouter la longueur du côté.

    super(...) dans le constructeur et super.describe() dans une méthode ont des rôles différents : le premier initialise la classe parente, le second appelle une méthode parente. Une sous-classe sans constructeur propre transmet automatiquement les arguments.

  13. 13
    DéfiChoisis un modèle adapté

    Un objet Report doit envoyer des messages par l’intermédiaire d’un Notifier. Les rapports ne sont pas des systèmes de notification. Quelle relation faut-il établir entre les objets et comment le rapport doit-il demander une notification ?

    ---reveal---

    Utilise la composition : donne au rapport une propriété contenant le système de notification, puis appelle une méthode comme this.notifier.send(message). C’est une relation « possède un ». Étendre Notifier reviendrait à affirmer que chaque rapport est lui-même un système de notification simplement pour réutiliser son code, ce qui ne correspond pas au modèle.

  14. 14
    ExplicationTrouve une méthode dans la chaîne

    Les propriétés propres d’un cercle contiennent des données comme son rayon. Lorsqu’il ne possède pas de propriété propre describe, JavaScript recherche dans Circle.prototype, puis dans Shape.prototype, où cette méthode est stockée.

    La chaîne ordinaire continue par Object.prototype jusqu’à null. Si aucun objet de la chaîne ne possède une propriété demandée, sa lecture donne undefined. instanceof Shape réussit normalement parce que Shape.prototype apparaît dans la chaîne de l’instance.

  15. 15
    ExempleMasque un paramètre hérité

    Crée settings avec Object.create(defaults), où defaults.fontSize vaut 16. Effectue l’affectation settings.fontSize = 18.

    L’affectation crée une propriété de données propre qui masque la propriété héritée. La valeur par défaut reste à 16. Supprimer settings.fontSize retire le masquage : la lecture suivante retrouve donc 16 sur le prototype. Ce suivi suppose une propriété de données ordinaire ; un accesseur en écriture hérité peut toutefois traiter une affectation à sa place.

  16. 16
    DéfiVérifie séparément si une propriété est propre et si elle est accessible

    Un objet panel hérite de theme: "light" d’un prototype ordinaire et ne possède pas sa propre propriété theme. Que produisent panel.theme, Object.hasOwn(panel, "theme") et "theme" in panel ?

    ---reveal---

    Ils produisent "light", false et true. La lecture et in peuvent trouver des propriétés héritées, tandis que Object.hasOwn vérifie uniquement si la propriété est stockée sur panel lui-même. Une lecture réussie ne prouve pas que la propriété est propre. Object.keys(panel) omet aussi cette clé héritée.

  17. 17
    DéfiRelie héritage, confidentialité et recherche

    Sensor déclare #value, un accesseur en lecture public value et une méthode describe() qui lit this.value. IndoorSensor extends Sensor n’ajoute aucun membre. Pourquoi un capteur intérieur peut-il appeler describe() alors que le corps de sa classe ne peut pas nommer #value ?

    ---reveal---

    La recherche trouve la méthode héritée, qui s’exécute avec le capteur intérieur comme this. L’accesseur en lecture déclaré dans Sensor peut lire son propre champ privé sur cette instance. L’héritage fournit le comportement public sans donner à la sous-classe un accès direct au nom privé de la classe parente.

  18. 18
    RécapitulatifExamine un objet dans un ordre utile

    Lorsque tu suis une instance de classe, demande-toi où ses données sont stockées, quel objet reçoit l’appel de méthode et où la recherche trouve la méthode. Si une modification passe par un accesseur en écriture, suis la validation avant l’affectation.

    Pour une hiérarchie inconnue, examine extends et les arguments du constructeur avant de suivre les méthodes redéfinies. Vérifie si les propriétés sont propres lorsque tu as besoin des clés stockées, et suis les prototypes lorsque tu dois expliquer un comportement hérité.

2

Relie un programme entre ses modules

13 étapes
Exporte une classe, charge-la dans l’un ou l’autre environnement et reporte un travail facultatif tout en gardant des dépendances claires.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionSuis un graphe de dépendances
  2. 2
    ExempleExporte le calcul
  3. 3
    ExempleExporte et utilise la classe
  4. 4
    DéfiLis une exportation modifiée
  5. 5
    ExempleLance les fichiers dans un navigateur
  6. 6
    ExplicationRésous un nom de paquet
  7. 7
    DéfiChoisis le système de chargement de Node.js
  8. 8
    ExempleReporte le chargement d’un graphique facultatif
  9. 9
    Point cléDétermine ce qui attend l’initialisation
  10. 10
    DéfiRomps un cycle inutile
  11. 11
    ConseilÉvite d’effectuer du travail à l’importation
  12. 12
    DéfiCombine le chargement avec une interface claire
  13. 13
    RécapitulatifSuis une erreur de module étape par étape
3

Recrée un projet npm sur un autre ordinateur

11 étapes
Lis les scripts, choisis les types de dépendances et utilise les plages de versions avec un fichier de verrouillage pour reproduire l’installation.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionRends le projet reproductible
  2. 2
    ExempleCrée la description du paquet
  3. 3
    ExempleLis la tâche avant de l’exécuter
  4. 4
    DéfiIdentifie un changement de version
  5. 5
    ExplicationEnregistre séparément le code et les outils
  6. 6
    ExempleLis ce qu’une plage autorise
  7. 7
    ExplicationInstalle l’arbre enregistré
  8. 8
    DéfiInterprète une installation propre bloquée
  9. 9
    ConseilPrévois une mise à jour réfléchie
  10. 10
    DéfiCombine une plage de versions et une compilation propre
  11. 11
    RécapitulatifLis ensemble les deux enregistrements du paquet
4

Vérifie un projet de la modification à la compilation

15 étapes
Utilise un linter, la mise en forme, la prévisualisation de production et les tests pour examiner différents types d’échecs.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionPose une question différente à chaque outil
  2. 2
    ExplicationConfigure un rapport de linter utile
  3. 3
    ExempleTrouve une faute de frappe avant l’exécution
  4. 4
    DéfiChoisis une vérification de mise en forme
  5. 5
    ExempleLance le développement, la compilation et la prévisualisation
  6. 6
    ExempleSuis une optimisation de compilation
  7. 7
    LienRelie les résultats aux sources
  8. 8
    DéfiChoisis ce qu’il faut reconstruire
  9. 9
    ExempleÉcris un résultat attendu indépendant
  10. 10
    Point cléCompare correctement les contenus et l’identité
  11. 11
    DéfiTeste la borne exacte
  12. 12
    ConseilAttends un test asynchrone
  13. 13
    ExempleUtilise une tolérance numérique adaptée
  14. 14
    DéfiExamine une compilation réussie avec un résultat incorrect
  15. 15
    RécapitulatifLis les échecs comme des éléments d’enquête
5

Intègre les types et les composants dans un projet fonctionnel

10 étapes
Distingue la vérification de l’exécution, puis détermine comment les outils du projet prennent en charge une interface utilisateur plus importante.

Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.

  1. 1
    IntroductionAjoute un outil pour un besoin précis
  2. 2
    ExempleRepère un appel incompatible
  3. 3
    ExplicationDistingue la transformation de la vérification
  4. 4
    DéfiVérifie les données qui arrivent à l’exécution
  5. 5
    ExplicationSitue un composant dans la méthode de travail
  6. 6
    ExempleLis le menu des tâches du projet
  7. 7
    DéfiDétermine quand un framework est utile
  8. 8
    DéfiTrouve la vérification manquante
  9. 9
    ConseilAdopte progressivement la vérification
  10. 10
    RécapitulatifSuis chaque outil jusqu’aux éléments qu’il fournit

Classes et modules JavaScript : QCM

50 Questions Pratiques en 5 séries

Série 1 : Lis des classes, des importations et des tâches de projet10 Questions Pratiques

Question 1 sur 10

Un module exporte une fonction par défaut et exporte aussi LIMIT par son nom. Comment une seule déclaration peut-elle importer la fonction sous le nom calculate et la constante sous son nom exporté ?
  1. import { calculate, LIMIT } from "./calc.js";
  2. import calculate, LIMIT from "./calc.js";
  3. import calculate, { LIMIT } from "./calc.js";
  4. import { default, LIMIT } from "./calc.js";
Afficher la réponseMasquer la réponse
Réponse : C
La liaison par défaut apparaît sans accolades, suivie de l’importation nommée entre accolades. Demander { calculate, LIMIT } revient à demander deux exportations nommées, mais la fonction a été fournie comme exportation par défaut. Le nom local calculate est choisi par le fichier importateur et n’a pas besoin de correspondre au nom de déclaration de la fonction.

Question 2 sur 10

Une classe déclare static created = 8;. Son instance est affectée à batch et la classe se nomme Batch. Comment lit-on le compteur stocké ?
  1. Batch.created
  2. new Batch().created
  3. Batch.prototype.created
  4. batch.constructor.prototype.created
Afficher la réponseMasquer la réponse
Réponse : A
Un champ statique appartient à la classe : le compteur se lit donc avec Batch.created. La lecture de batch.created recherche dans l’instance et sa chaîne de prototypes, où ce champ statique n’a pas été placé. Statique ne signifie pas qu’un champ est copié sur chaque objet.

Question 3 sur 10

Pourquoi ce constructeur échoue-t-il et quel ordre corrige le problème ?

class Item {
  constructor(code) { this.code = code; }
}
class Box extends Item {
  constructor(code) {
    this.open = false;
    super(code);
  }
}
new Box("K7");
  1. Il omet un champ propre code ; affecte d’abord this.code.
  2. Il hérite d’un constructeur ; supprime l’appel à super(code).
  3. Il transmet une chaîne à la classe parente ; convertis d’abord code.
  4. Il utilise this trop tôt ; appelle d’abord super(code).
Afficher la réponseMasquer la réponse
Réponse : D
Un constructeur dérivé ne peut pas utiliser this avant que le constructeur parent ait initialisé l’instance avec super(code). Déplace cet appel avant l’affectation de open. Affecter d’abord un autre champ poserait le même problème, car cela accéderait encore à this trop tôt.

Question 4 sur 10

Un module contient uniquement export default class Badge {}. Quelle importation lie cette classe au nom local Tag ?
  1. import { Tag } from "./badge.js";
  2. import Tag from "./badge.js";
  3. import { Badge as Tag } from "./badge.js";
  4. import * as Tag from "./badge.js";
Afficher la réponseMasquer la réponse
Réponse : B
Une importation par défaut n’utilise pas d’accolades et peut choisir le nom local Tag. Importer { Badge as Tag } demande au contraire une exportation nommée Badge, que ce module ne fournit pas. Une importation dans un espace de noms lierait un objet contenant l’exportation par défaut, pas la classe elle-même.

Question 5 sur 10

Un fichier d’entrée pour navigateur contient une déclaration import, mais sa balise script n’a pas d’attribut type. Quelle modification HTML en fait un module ES ?
  1. Ajouter uniquement defer à sa balise script.
  2. Ajouter uniquement async à sa balise script.
  3. Ajouter type="module" à sa balise script.
  4. Ajouter type="text/javascript" à sa balise script.
Afficher la réponseMasquer la réponse
Réponse : C
type="module" indique au navigateur d’utiliser la syntaxe et les règles de chargement des modules ES. Ajouter uniquement defer modifie le moment d’exécution d’un script classique, mais n’y rend pas les déclarations d’importation valides. Le module d’entrée peut alors charger automatiquement ses dépendances lorsque les fichiers sont correctement servis.

Question 6 sur 10

Un projet possède "scripts": { "check": "eslint ." }. Quelle commande exécute cette tâche nommée ?
  1. npm check
  2. npm install check
  3. node check
  4. npm run check
Afficher la réponseMasquer la réponse
Réponse : D
Les noms de scripts personnalisés ordinaires s’exécutent avec npm run : cette tâche s’exécute donc avec npm run check. npm check ne devient pas une forme courte simplement parce qu’un script porte ce nom ; les formes courantes npm test et npm start sont des cas particuliers. Le script exécute la commande ESLint enregistrée.

Question 7 sur 10

Un projet utilise un formateur de code uniquement pendant le développement. Dans quelle section de package.json faut-il normalement enregistrer l’entrée de ce paquet comme dépendance directe ?
  1. devDependencies
  2. dependencies
  3. scripts
  4. engines
Afficher la réponseMasquer la réponse
Réponse : A
Un formateur de code est un outil de développement : son paquet appartient donc à devDependencies, où il est normalement ajouté avec npm install -D. La section des scripts peut contenir une commande qui l’exécute, mais cela n’enregistre pas la dépendance au paquet. Le code de bibliothèque nécessaire à l’exécution appartient à dependencies.

Question 8 sur 10

Une exécution d’ESLint signale un avertissement et aucune erreur, avec ses réglages de sortie habituels. Que prouve une fin d’exécution réussie au sujet du code ?
  1. Aucune règle ne s’est déclenchée ; l’avertissement ne concerne que la mise en forme.
  2. Tout comportement est correct ; l’avertissement ne peut pas toucher l’exécution.
  3. Aucune règle de niveau erreur n’a échoué ; l’avertissement reste à examiner.
  4. L’avertissement a été corrigé ; le linter modifie toujours les fichiers s’il réussit.
Afficher la réponseMasquer la réponse
Réponse : C
Par défaut, les avertissements sont signalés sans faire échouer ESLint : une exécution réussie peut donc comporter un avertissement. Elle ne prouve pas que le comportement est correct : le linter recherche les constructions prévues par sa configuration sans exécuter le programme. Les modifications automatiques nécessitent une commande de correction et un problème pour lequel une correction existe.

Question 9 sur 10

Une fonction renvoie un tableau nouvellement créé contenant "a" et "b". Comment un test Vitest doit-il vérifier ce contenu par rapport à un littéral de tableau distinct ?
  1. expect(result).toBe(["a", "b"]);
  2. expect(result).toEqual(["a", "b"]);
  3. expect(result === ["a", "b"]).toBe(true);
  4. expect(Object.is(result, ["a", "b"])).toBe(true);
Afficher la réponseMasquer la réponse
Réponse : B
toEqual vérifie le contenu du tableau, y compris l’ordre de ses valeurs. toBe et les expressions d’identité vérifient si les deux opérandes sont le même objet ; un littéral de tableau distinct crée un autre objet. Pour vérifier l’égalité des contenus, il faut donc la comparaison profonde présentée.

Question 10 sur 10

Une fonction déclarée pour accepter des nombres reçoit des données analysées provenant d’un serveur. Une compilation Vite réussit, mais le programme en cours d’exécution concatène une chaîne alors qu’une somme était prévue. Le projet ne possède ni tâche distincte de vérification des types ni contrôle des données à l’exécution. Quels changements traitent ces deux points non vérifiés ?
  1. Exécuter un vérificateur de types et valider les valeurs analysées avant le calcul.
  2. Exécuter le formateur de code et déclarer numériques les données analysées.
  3. Exécuter un vérificateur de types et faire confiance à toute réponse de serveur typée.
  4. Exécuter une prévisualisation de production et supprimer les annotations de type.
Afficher la réponseMasquer la réponse
Réponse : A
Vite peut supprimer les types sans les vérifier : un vérificateur distinct traite donc les erreurs de type dans le code source. La valeur réellement envoyée par le serveur doit toujours être validée à l’exécution, car les déclarations n’examinent pas les données reçues. La vérification des types seule ne peut pas prouver que la réponse respecte la structure déclarée.
Série 2 : Utilise les modules et des réglages de projet reproductibles10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Que se passe-t-il à la dernière ligne ?

class Meter {
  value = 2;
  read() { return this.value; }
}
const meter = new Meter();
const read = meter.read;
read();
  1. Elle renvoie 2, car l’affectation d’une méthode préserve son objet receveur.
  2. Elle lève une exception, car this vaut undefined dans l’appel détaché.
  3. Elle renvoie undefined, car le champ de classe est privé.
  4. Elle lève une exception, car les méthodes d’instance ne peuvent pas être affectées à des variables.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Quel est le dernier résultat ?

const base = { unit: "cm" };
const sample = Object.create(base);
Object.hasOwn(sample, "unit");
  1. true
  2. "cm"
  3. undefined
  4. false
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Que renvoie l’expression finale ?

class Label {
  constructor(text) { this.text = text; }
  length() { return this.text.length; }
}
new Label("Orbit").length();
  1. 5
  2. 4
  3. undefined
  4. "Orbit"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Que renvoie immédiatement import("./help.js") ?
  1. La valeur elle-même exportée par défaut par le module.
  2. Un nouvel espace de noms évalué de manière synchrone.
  3. Une promesse dont le résultat sera l’objet d’espace de noms du module.
  4. Un tableau contenant toutes les valeurs exportées.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Un paquet stable en version 7.3.6 publie une correction de bogue compatible sans nouvelle fonctionnalité. Quelle version suivante respecte le versionnement sémantique ?
  1. 7.4.0
  2. 7.3.7
  3. 8.0.0
  4. 7.3.6
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un projet autorise ~6.4.2. Quelle est la version stable autorisée la plus récente parmi 6.4.9, 6.5.0, 7.0.0 et 6.4.1 ?
  1. 6.4.9
  2. 6.5.0
  3. 7.0.0
  4. 6.4.1
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Dans un projet Vite, quelle tâche écrit les fichiers de production optimisés dans le dossier de sortie habituel ?
  1. npm run dev
  2. npm run preview
  3. npm install
  4. npm run build
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un test appelle une fonction asynchrone loadItems() sans l’attendre. La fonction de rappel du test se termine ; la promesse est ensuite tenue avec un nouveau tableau. L’assertion prévue utilise toBe(["x"]). Que faut-il changer pour que le test vérifie de manière fiable le contenu obtenu par la promesse ?
  1. Terminer immédiatement le test et utiliser toEqual(["x"]).
  2. Attendre loadItems() dans un test asynchrone et garder toBe(["x"]).
  3. Attendre loadItems() dans un test asynchrone et utiliser toEqual(["x"]).
  4. Garder l’appel sans attente et vérifier la promesse avec toBe(["x"]).
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un programme .ts s’exécute dans Node.js grâce à l’effacement des types pris en charge. Pourquoi cette exécution réussie ne prouve-t-elle pas que tous les types déclarés sont corrects ?
  1. Node.js convertit chaque valeur reçue dans son type déclaré.
  2. Les annotations de type ne restent actives que jusqu’au premier appel de fonction.
  3. L’effacement des types supprime la syntaxe sans vérifier les types.
  4. Node.js ne vérifie les types que pour le code qui utilise les API du navigateur.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une équipe installe un framework de composants, ESLint et un exécuteur de tests dans un modèle Vite. Seuls les scripts de développement et de compilation d’origine existent ; il n’y a ni configuration du linter ni code de test. Quel travail reste nécessaire pour obtenir des vérifications reproductibles du code et du comportement ?
  1. Réinstaller les outils globalement et s’appuyer sur le script de compilation existant.
  2. Configurer le linter, écrire des assertions et rendre les vérifications accessibles par des scripts.
  3. Ajouter seulement des noms de scripts et laisser les paquets installés déduire le comportement.
  4. Déplacer les outils dans les dépendances d’exécution et recompiler le modèle.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 3 : Suis l’état, les dépendances et le comportement de la compilation10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Un accesseur en écriture n’accepte que les nombres finis de 4 à 9 inclus. Son instance stocke 6. L’accesseur vérifie l’entrée avant l’affectation et lève une exception en cas d’échec. Après interception de l’erreur provoquée par une tentative d’affectation de "8", quelle valeur reste et pourquoi ?
  1. 8 reste, car la vérification de l’intervalle convertit la chaîne.
  2. 6 reste, car les champs privés rejettent tout appel à l’accesseur.
  3. 9 reste, car l’accesseur ramène les valeurs invalides au maximum.
  4. 6 reste, car la chaîne échoue à la vérification du nombre fini.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Quelles sont les valeurs lues à la fin ?

const base = { value: 4, read() { return this.value; } };
const x = Object.create(base);
const y = Object.create(x);
x.value = 7;
y.value = 10;
delete y.value;
[y.read(), Object.hasOwn(y, "read"), base.value];
  1. [4, false, 4]
  2. [7, false, 4]
  3. [7, true, 7]
  4. [10, false, 4]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

Quelles sont les deux valeurs finales ?

const defaults = { size: 11 };
const item = Object.create(defaults);
item.size = 15;
delete item.size;
[item.size, defaults.size];
  1. [undefined, 11]
  2. [15, 15]
  3. [11, 11]
  4. [undefined, undefined]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un module exécuté directement dans un navigateur importe "tiny-calendar". Le paquet est installé localement, mais le navigateur signale un spécificateur non résolu. Quel type de configuration manquante explique ce problème ?
  1. Une correspondance ou un outil qui résout le nom nu en code chargeable par le navigateur.
  2. Une seconde installation qui copie le paquet dans des variables globales.
  3. Un réglage de type CommonJS qui fait chercher le navigateur dans node_modules.
  4. Un attribut async qui reporte la résolution du nom nu après l’analyse.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

main.js importe statiquement config.js, qui attend une réponse réseau avant d’exporter des paramètres. Un point d’entrée indépendant clock.js n’importe aucun des deux fichiers. Plus tard, le gestionnaire asynchrone de main exécute const plugin = await import("./plugin.js") ; ce module n’exporte que la classe Plugin par défaut. Quelle réponse décrit correctement l’attente et la construction ?
  1. Les deux points d’entrée attendent config ; construis avec new plugin.default().
  2. Main attend config ; clock peut continuer ; construis avec new plugin().
  3. Aucun point d’entrée n’attend config ; construis avec new plugin.Plugin().
  4. Main attend config ; clock peut continuer ; construis avec new plugin.default().
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Des fichiers de paquets concordants déclarent ^8.1.0 et verrouillent une dépendance à la version 8.1.3. Une compilation propre exécute npm ci après la publication de 8.7.0. Quelle version est installée ?
  1. 8.7.0
  2. 8.1.0
  3. 8.1.3
  4. La version 9.x la plus récente.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Une personne doit examiner les résultats de production Vite existants à l’aide d’un serveur HTTP local. Quelle tâche du projet permet normalement de le faire ?
  1. npm run dev
  2. npm run preview
  3. npm run build
  4. npm init -y
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Un point d’entrée importe une fonction utilitaire pure d’un module qui en exporte deux et effectue aussi un enregistrement nécessaire au niveau supérieur. Une compilation de production Vite minifie les résultats et inclut une fonctionnalité chargée à la demande. Quelle affirmation sur les résultats est justifiée ?
  1. Le code utilitaire inutilisé peut être supprimé, l’enregistrement nécessaire conservé et le code à la demande séparé.
  2. Tout code non importé, y compris l’enregistrement, doit disparaître dans un fichier chargé immédiatement.
  3. Les deux fonctions doivent rester, l’enregistrement est supprimé et le code à la demande est intégré.
  4. Chaque fichier source doit devenir un fichier de sortie avec tous les noms d’origine conservés.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Quelle commande vérifie un projet TypeScript sans écrire de JavaScript en sortie ?
  1. vite build
  2. node app.ts
  3. prettier . --check
  4. tsc --noEmit
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Une application appelle une fonction de mise en forme des dates lorsqu’elle en a besoin. Un système d’interface utilisateur appelle au contraire le code des composants de l’application lorsqu’un rendu est nécessaire. Quelle distinction ces exemples illustrent-ils ?
  1. Une bibliothèque fournit des fonctions utilitaires appelables ; un framework coordonne les appels au code de l’application.
  2. Un framework fournit des fonctions utilitaires appelables ; une bibliothèque coordonne tout le rendu de l’application.
  3. Une bibliothèque remplace les modules ; un framework remplace l’installation des paquets et les compilations.
  4. Un framework vérifie les types à l’exécution ; une bibliothèque ne les vérifie que pendant le développement.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 4 : Diagnostique les problèmes de classes et de projets10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Quelles sont les valeurs lues à la fin ?

class Counter {
  count = 1;
  add() { this.count += 2; }
}
const a = new Counter();
const b = new Counter();
const addA = a.add.bind(a);
b.count = 10;
addA();
const callB = () => b.add();
callB();
[a.count, b.count];
  1. [3, 12]
  2. [1, 14]
  3. [12, 12]
  4. [3, 10]
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Une classe stocke tout son état dans le champ privé #level et fournit un accesseur en lecture public sur son prototype. Elle ne définit pas de méthode toJSON. Que produit JSON.stringify(new Gauge()) ?
  1. "{\"level\":0}"
  2. "{\"#level\":0}"
  3. "{}"
  4. undefined
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

class Photo extends Asset {} est déclarée sans constructeur. Asset stocke l’argument transmis à son constructeur. Que devient l’argument dans new Photo("P8") ?
  1. Il est ignoré parce que le constructeur de la sous-classe est absent.
  2. Le constructeur par défaut de la sous-classe le transmet à Asset.
  3. Il devient un champ statique de la classe Photo.
  4. Il n’est stocké que si Photo redéfinit toutes les méthodes héritées.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un module exporte let count = 1, un objet state = { count: 1 } et advance(), qui augmente les deux compteurs. Deux autres modules importent ces mêmes exportations. Le premier appelle advance(), puis effectue l’affectation state.count = 9. Que lit le second avec [count, state.count] et peut-il réaffecter count ?
  1. Il lit [1, 1] et peut réaffecter sa copie importée privée.
  2. Il lit [2, 2] et peut réaffecter les deux liaisons importées.
  3. Il lit [1, 9] et ne voit pas les modifications des valeurs primitives exportées.
  4. Il lit [2, 9] et ne peut pas réaffecter le count importé.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Un module déclare save() et un bouton utilise onclick="save()" en ligne. Le module se charge correctement, mais un clic signale que save n’est pas défini. Comment faut-il relier l’événement ?
  1. Ajouter defer en gardant le gestionnaire en ligne inchangé.
  2. Attacher save avec addEventListener depuis le module.
  3. Exporter save et compter sur HTML pour importer automatiquement son nom.
  4. Renommer le fichier en .mjs en gardant le gestionnaire en ligne.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Les scripts d’un projet contiennent "inspect": "eslint src". Quelle commande exécute ce script avec l’argument --fix d’ESLint ?
  1. npm run inspect -- --fix
  2. npm run inspect --fix
  3. npm install inspect -- --fix
  4. npm inspect src --fix
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Une configuration ESLint partagée impose un style de guillemets contraire à celui de Prettier. Les guillemets des fichiers enregistrés changent sans cesse. Le code renvoie aussi un nom non défini qui déclenche no-undef. Quelle configuration supprime le conflit de mise en forme tout en conservant cette vérification utile des bogues ?
  1. Désactiver les règles de style et no-undef, puis utiliser un seul formateur.
  2. Garder les règles de style incompatibles et no-undef, puis utiliser un seul formateur.
  3. Désactiver les règles de style incompatibles, garder no-undef et utiliser un seul formateur.
  4. Désactiver les règles de style, garder no-undef et conserver les formateurs concurrents.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Quel type de problème la commande --write de Prettier modifie-t-elle directement ?
  1. Les résultats attendus stockés dans les assertions de comportement.
  2. Les noms de variables incorrects déduits des données d’exécution.
  3. Les versions publiées autorisées par les plages de dépendances.
  4. Les espaces et la présentation des fichiers sources pris en charge.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Un contrôle doit accepter les longueurs numériques finies de 0 à 12 cm inclus. Quels trois résultats attendus dans les tests révèlent des défauts distincts de cette implémentation ?

function setLength(n) {
  if (n <= 0 || n > 12) throw new RangeError();
  return n;
}
  1. Accepter 0 ; rejeter "7" ; rejeter NaN.
  2. Accepter 12 ; rejeter "7" ; rejeter NaN.
  3. Accepter 0 ; accepter "7" ; rejeter NaN.
  4. Accepter 0 ; rejeter "7" ; accepter NaN.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Un site statique utilise des outils npm pour produire les fichiers du navigateur. Quel est le rôle du dossier dist dans cette méthode de travail ?
  1. La configuration source à modifier avant chaque compilation.
  2. L’enregistrement exact des dépendances qui remplace le fichier de verrouillage npm.
  3. Les fichiers générés qui peuvent être servis par un hébergeur statique adapté.
  4. Les outils de développement installés que chaque navigateur télécharge séparément.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Série 5 : Combine les notions dans des projets inconnus10 Questions Pratiques

Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.

Question 1 sur 10

Que renvoie new LoudNote("A").describe() ?

class Note {
  constructor(text) { this.text = text; }
  label() { return this.text; }
  describe() { return "[" + this.label() + "]"; }
}
class LoudNote extends Note {
  label() { return super.label() + "!"; }
  describe() { return super.describe() + "?"; }
}
  1. "[A]!?"
  2. "[A]?"
  3. "[A!]?"
  4. "[A!?]"
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 2 sur 10

Que renvoie l’appel final ?

class Base {
  constructor(n) { this.n = n; }
  value() { return this.n; }
  report() { return this.value() + 1; }
}
class Double extends Base {
  value() { return super.value() * 2; }
}
class Extra extends Double {
  report() { return super.report() + 3; }
}
new Extra(4).report();
  1. 8
  2. 9
  3. 16
  4. 12
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 3 sur 10

feature.js possède une exportation par défaut et une exportation nommée ready. Un fichier barrel contient uniquement export * from "./feature.js";. Que transmet ce fichier barrel ?
  1. Les deux exportations, celle par défaut étant renommée feature.
  2. L’exportation nommée ready, sans transmettre celle par défaut.
  3. L’exportation par défaut seule, les exportations nommées restant privées.
  4. Aucune des deux, car un fichier barrel doit les évaluer en appelant des fonctions.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 4 sur 10

Un module de données importe un module d’interface utilisateur au niveau supérieur pour effectuer immédiatement le rendu. L’interface importe le module de données et lit une liaison non initialisée. Les tests unitaires qui importent les données tentent aussi d’accéder à document dans Node.js. Quelle réorganisation résout ces deux échecs ?
  1. Déplacer la connexion des événements dans le module d’entrée et rendre la logique de données partagée indépendante de l’interface.
  2. Retarder les mêmes importations circulaires avec une minuterie et ajouter un nom document global.
  3. Placer toutes les définitions partagées dans un fichier barrel plus grand et garder le rendu à l’importation.
  4. Intercepter chaque erreur d’importation et relancer le module d’interface inchangé jusqu’à son initialisation.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 5 sur 10

Qu’empêche directement "private": true dans package.json ?
  1. L’importation de ses fonctions exportées par d’autres modules.
  2. La lecture des fichiers sources compilés par les utilisateurs du navigateur.
  3. La publication accidentelle du paquet par npm.
  4. L’installation des dépendances de développement du projet par npm.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 6 sur 10

Un projet déclare ^0.6.2, verrouille la version 0.6.4 et possède un fichier de verrouillage valide et concordant. Le registre propose 0.6.9 et 0.7.0. Quelle suite indique la version après npm ci, puis la version autorisée la plus récente après un npm update délibéré ?
  1. D’abord 0.6.9, puis 0.7.0.
  2. D’abord 0.6.4, puis 0.6.9.
  3. D’abord 0.6.4, puis 0.7.0.
  4. D’abord 0.6.2, puis 0.6.4.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 7 sur 10

Un fichier source front-end lit un identifiant secret dans une variable personnalisée VITE_. Pourquoi cet emplacement ne convient-il pas à cet identifiant, même après minification ?
  1. La variable n’existe que dans l’éditeur et disparaît avant la compilation.
  2. Le préfixe ne chiffre la valeur que lorsque le mode développement est actif.
  3. La valeur est protégée sauf si une carte des sources est aussi publiée.
  4. La valeur exposée est envoyée aux utilisateurs du navigateur et peut être examinée.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 8 sur 10

Une fonction doit rejeter un nom vide en levant RangeError. Quelle assertion Vitest permet à la méthode de vérification d’observer l’exception ?
  1. expect(() => createName("")).toThrow(RangeError);
  2. expect(createName("")).toThrow(RangeError);
  3. expect(() => createName("")).toBe(RangeError);
  4. expect(createName).toEqual(new RangeError());
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 9 sur 10

Une classe utilise private value de TypeScript, lui affecte une entrée réseau analysée et renvoie un résultat numérique avec une formule incorrecte. Le projet passe tsc --noEmit. Quelle combinaison traite la confidentialité à l’exécution, l’entrée externe et le comportement ?
  1. Garder le mot-clé private, affirmer le type de la réponse et répéter la formule dans les tests.
  2. Utiliser un champ JavaScript #, valider l’entrée et tester des résultats attendus indépendants.
  3. Utiliser un champ JavaScript #, se fier à l’annotation de la réponse et lancer la mise en forme.
  4. Valider l’entrée, désactiver la vérification avec any et se fier à une compilation réussie.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Question 10 sur 10

Un projet de composants se compile correctement, mais il a besoin d’URL de pages coordonnées et d’un HTML initial rendu sur le serveur. Quelle couche de projet plus large fournit couramment ces deux fonctionnalités autour de l’interface à composants ?
  1. Un routeur côté client qui ne s’exécute qu’après le chargement de JavaScript.
  2. Une page de repli statique sans étape de rendu sur le serveur.
  3. Un stockage de l’état des composants sans intégration du routage.
  4. Un méta-framework avec routage et rendu sur le serveur.
Afficher la réponseMasquer la réponse

Enregistre cette unité pour voir cette réponse.

Tu bloques sur ton propre exercice ? Aide aux Devoirs

Mots-Clés

88 Mots-Clés, chacun avec sa définition

A

Accesseur en écriture
Un accesseur en écriture est une méthode d’accès qui s’exécute lorsqu’une valeur est affectée à une propriété, ce qui permet de la valider avant de modifier le stockage.
Un accesseur en écriture de la consigne peut rejeter une température hors de l’intervalle autorisé avant de l’affecter à un champ privé.
Accesseur en lecture
Un accesseur en lecture est une méthode d’accès qui s’exécute lorsqu’une propriété est lue, ce qui permet de calculer ou d’exposer une valeur sans parenthèses d’appel.
La lecture de thermostat.target peut invoquer un accesseur en lecture qui renvoie la température de consigne stockée dans un champ privé.
Analyse statique
L’analyse statique examine le code sans l’exécuter, en utilisant sa structure écrite et des règles configurées pour identifier les problèmes potentiels.
Un diagnostic de nom non défini peut apparaître dans l’éditeur avant que l’application n’exécute cette ligne.
Annotation de type
Une annotation de type indique dans le code source le type ou la structure attendus d’une valeur et fournit des informations pour la vérification statique.
L’annotation d’un paramètre numérique aide un éditeur à rejeter un appel incompatible avant l’exécution de la fonction.
Assertion
Une assertion est une instruction de test qui vérifie une propriété précise attendue d’un résultat et signale un échec lorsque cette attente n’est pas satisfaite.
Une assertion peut vérifier qu’une longueur de côté invalide lève une exception au lieu de créer un rectangle utilisable.
Audit des dépendances
Un audit des dépendances compare les versions des paquets installés aux rapports de vulnérabilités connues et produit des résultats à examiner et à corriger.
Un résultat d’audit doit être lu pour déterminer si le code concerné est utilisé et quels correctifs compatibles existent.
Await au niveau supérieur
Await au niveau supérieur permet à un module ES d’attendre hors d’une fonction pendant son évaluation, ce qui retarde les modules qui dépendent de cette évaluation.
Un module de paramètres peut terminer la récupération de la configuration avant que le module d’entrée qui en dépend ne commence à exécuter son corps.

B

Bibliothèque
Une bibliothèque fournit du code réutilisable que le code de l’application appelle selon ses besoins, en laissant au programme appelant le contrôle de ces demandes.
Une application appelle une fonction utilitaire de mise en forme des dates lorsqu’elle doit afficher un horodatage dans l’interface.
Bloc d’initialisation statique
Un bloc d’initialisation statique est un bloc situé dans une classe qui s’exécute une fois lors de sa définition pour effectuer une initialisation au niveau de la classe.
Une classe peut remplir une table de correspondance partagée dans un bloc statique sans répéter cette initialisation pour chaque objet.
Bundler
Un bundler suit les dépendances d’un programme et les combine ou les transforme en fichiers de sortie adaptés à leur mise à disposition des utilisateurs.
Une compilation pour navigateur peut résoudre les paquets installés et écrire des fichiers optimisés dans le dossier généré dist.

C

Carte d’importation
Une carte d’importation est une configuration du navigateur qui associe des spécificateurs de module à des URL afin que les importations utilisent des noms que le navigateur ne pourrait pas résoudre seul.
Une page place sa carte d’importation avant ses scripts de module pour associer un nom de paquet court à une URL de serveur.
Carte des sources
Une carte des sources relie les positions du code généré à celles des fichiers sources d’origine, ce qui facilite le débogage des résultats transformés.
Une trace de pile peut indiquer la fonction d’origine lorsque le navigateur dispose de la carte correspondante.
Chaîne de prototypes
Une chaîne de prototypes est la succession de liens suivis lors de la recherche d’une propriété, qui se termine par null lorsqu’il n’existe plus de prototype.
Un cercle peut trouver sa description sur Shape.prototype après que la recherche est passée par Circle.prototype.
Champ d’instance
Un champ d’instance est une propriété déclarée pour chaque objet créé à partir d’une classe, qui donne à chaque instance sa propre valeur stockée.
Un champ de compteur initialisé à zéro démarre séparément sur chaque nouvel objet compteur.
Champ privé
Un champ privé est un espace de stockage déclaré dans une classe dont le nom commence par # et auquel seule la classe qui déclare ce nom peut accéder directement.
Une classe enfant utilise l’accesseur en lecture public de sa classe parente au lieu de nommer directement un champ de consigne privé déclaré par celle-ci.
Classe
Une classe est un modèle permettant de créer des objets ayant une structure commune et des comportements partagés, à l’aide de constructeurs, de champs et de méthodes.
Une classe Rectangle peut créer plusieurs formes dont les méthodes d’aire utilisent leurs propres largeurs et hauteurs.
CommonJS
CommonJS est le système de modules d’origine de Node.js, qui utilise des appels require synchrones et module.exports pour fournir des valeurs.
Un fichier .cjs reste en CommonJS même lorsque le paquet qui le contient sélectionne explicitement les modules ES.
Composant
Un composant est une partie réutilisable d’une interface utilisateur qui regroupe du balisage et un comportement, souvent avec des styles et un état qui influent sur son affichage.
Un composant de navigation peut apparaître sur plusieurs pages tout en gardant son code d’interaction au même endroit.
Composition d’objets
La composition d’objets construit un comportement en donnant à un objet d’autres objets auxquels déléguer du travail, ce qui exprime une relation « possède un » entre eux.
Un rapport contient un système de notification et lui demande d’envoyer un message sans devenir lui-même un type de système de notification.
Configuration à plat
La configuration à plat est le format de configuration actuel d’ESLint fondé sur JavaScript, qui combine des objets de configuration et des réglages de règles.
Un module eslint.config.js peut exporter les vérifications recommandées ainsi que les variables globales disponibles dans le code du navigateur.
Constructeur
Un constructeur est la méthode spéciale d’une classe qui s’exécute lors de la création d’une instance et initialise l’objet à partir des arguments fournis.
Un constructeur de rectangle stocke sa largeur et sa hauteur pour que les appels de méthodes ultérieurs puissent calculer son aire.

D

Définition de type
Une définition de type décrit les types du code existant pour les outils ; elle est souvent fournie dans des fichiers .d.ts ou des paquets de définitions distincts.
Une bibliothèque JavaScript peut fournir des informations de complétion et de vérification à l’éditeur sans réécrire son code d’exécution.
Dépendance
Une dépendance est un paquet dont le projet a besoin ; les paquets d’exécution sont normalement enregistrés dans la section dependencies de package.json.
Une bibliothèque de mise en forme des dates appelée par l’application est une dépendance d’exécution, même si elle est regroupée pour le navigateur.
Dépendance circulaire
Une dépendance circulaire est un cycle d’importation dans lequel des modules dépendent les uns des autres directement ou par l’intermédiaire d’autres modules du graphe.
Déplacer une fonction utilitaire partagée par un module de données et un module de rendu dans un troisième module indépendant peut supprimer le cycle d’importation entre eux.
Dépendance de développement
Une dépendance de développement est un paquet nécessaire pour développer, vérifier ou compiler un projet, plutôt que pour servir de code de bibliothèque à son exécution.
Un formateur de code ou un exécuteur de tests est généralement installé avec -D afin que sa version soit enregistrée pour le projet.
Dépendance transitive
Une dépendance transitive est un paquet nécessaire indirectement parce que l’une des dépendances du projet, ou l’une de leurs dépendances, en a besoin.
Le fichier de verrouillage enregistre les paquets imbriqués même lorsque l’application ne les importe jamais directement.
Développement piloté par les tests
Le développement piloté par les tests commence par un test de comportement qui échoue, ajoute juste assez de code pour le faire réussir, puis améliore le code tout en gardant les tests au vert.
Une nouvelle règle de validation peut d’abord être exprimée par un test qui échoue avant l’implémentation de son contrôle.

E

Effacement des types
L’effacement des types supprime la syntaxe de type prise en charge pour permettre l’exécution, sans vérifier lui-même que les types sont utilisés de manière cohérente.
Un fichier TypeScript peut s’exécuter grâce à l’effacement des types de Node.js même si un vérificateur distinct signalerait une erreur.
Effet de bord
Un effet de bord est une action observable qui va au-delà du renvoi d’une valeur, comme modifier un état partagé, mettre la page à jour ou enregistrer un comportement.
Un module qui modifie la page à l’importation est plus difficile à tester sans environnement de navigateur.
Empreinte du contenu
Une empreinte du contenu dans le nom d’un fichier de ressource change avec son contenu, ce qui aide les caches à distinguer un nouveau fichier d’une version plus ancienne.
Une ressource de compilation modifiée reçoit un nouveau nom contenant une empreinte afin que les navigateurs puissent la demander tout en gardant les fichiers inchangés en cache.
Encapsulation
L’encapsulation garde l’état interne derrière une interface publique contrôlée, dont les opérations respectent les règles qui rendent les modifications valides.
Un thermostat permet aux appelants de demander une modification de consigne, tandis que son accesseur en écriture détermine si l’entrée est valide.
Espace de noms de module
Un espace de noms de module est un objet qui expose les exportations d’un module sous forme de propriétés, y compris default lorsqu’une exportation par défaut existe.
Attendre une importation dynamique donne un espace de noms dans lequel l’appelant sélectionne le constructeur exporté.
Exécuteur de tests
Un exécuteur de tests trouve et exécute les tests, signale les résultats et renvoie normalement un code de sortie indiquant un échec lorsqu’un test échoue.
Un script de projet peut invoquer l’exécuteur de Node.js ou Vitest avant le partage des modifications avec un membre de l’équipe.
Exportation nommée
Une exportation nommée expose une déclaration sous un nom d’exportation précis que les fichiers importateurs demandent entre accolades dans une déclaration d’importation.
Un module de bornes exporte MAX, qu’un fichier importateur peut demander directement ou renommer localement.
Exportation par défaut
Une exportation par défaut fournit l’unique valeur par défaut d’un module, importée sans accolades sous un nom local choisi par le fichier importateur.
Une classe exportée par défaut peut être importée sous le nom Circle même si un autre fichier lui donne un nom local différent.

É

État
L’état est l’ensemble des données qui représentent la condition actuelle d’une interface et dont les changements peuvent amener le système d’interface utilisateur à mettre à jour ce que voient les utilisateurs.
Changer la tâche sélectionnée peut mettre à jour plusieurs vues qui dépendent toutes de cet état partagé.

F

Fichier barrel
Un fichier barrel rassemble les réexportations de plusieurs modules en un seul point d’importation, ce qui facilite l’accès à leur interface commune.
Un fichier barrel volumineux peut masquer une dépendance circulaire lorsqu’un module importe par l’index de son propre dossier.
Fichier de verrouillage
Un fichier de verrouillage enregistre l’arbre exact des dépendances sélectionnées afin que les installations puissent reproduire les versions sans résoudre de nouveaux choix à chaque fois.
Une compilation utilise des enregistrements de paquet concordants avec npm ci pour recréer l’arbre verrouillé sur un autre ordinateur.
Fonction constructeur
Une fonction constructeur est une fonction utilisée avec new pour initialiser des objets, souvent associée à des méthodes affectées à son prototype.
Du code JavaScript ancien peut ajouter area à Rectangle.prototype après avoir défini une fonction constructeur.
Formateur de code
Un formateur de code réécrit la présentation du code de manière cohérente en organisant les espaces, les retours à la ligne, l’indentation et les autres choix de style pris en charge.
Prettier peut normaliser les espaces d’un objet sans décider si celui-ci contient les bonnes valeurs.
Fractionnement du code
Le fractionnement du code divise le code compilé en fragments chargeables séparément, afin que certaines fonctionnalités puissent être récupérées plus tard plutôt qu’au démarrage initial.
Une importation dynamique pour un éditeur rarement utilisé peut donner à un outil de compilation un point de séparation pour un chargement ultérieur.
Framework
Un framework fournit une structure d’application et coordonne les moments où le code fourni par l’utilisateur s’exécute dans cette structure.
Un framework d’interface utilisateur peut appeler le code d’un composant lorsqu’un changement d’état nécessite de mettre à jour l’interface affichée.

H

Héritage
L’héritage permet à une sous-classe de s’appuyer sur les comportements d’une classe parente, en exprimant une relation « est un » entre les types d’objets modélisés.
Un cercle hérite de la description d’une forme mais fournit un calcul adapté à sa propre aire.

I

Importation dynamique
Une importation dynamique est une expression import() qui charge un module à la demande et renvoie une promesse dont le résultat sera son espace de noms.
Un gestionnaire de bouton asynchrone peut charger un graphique facultatif uniquement lorsque l’utilisateur demande à l’afficher.
Installation propre
Une installation propre recrée l’arbre des dépendances enregistré avec npm ci, en exigeant un fichier de verrouillage concordant et en remplaçant les paquets installés existants.
Si la description du paquet et le fichier de verrouillage ne concordent pas, une installation propre échoue au lieu de les réécrire silencieusement.
Instance
Une instance est un objet individuel créé à partir d’une classe, avec son propre état et un accès aux comportements fournis par cette classe.
Deux instances de rectangle peuvent partager une méthode d’aire tout en stockant des dimensions différentes en centimètres.
Interface
Une interface décrit une structure d’objet attendue pour la vérification TypeScript, y compris les propriétés et les méthodes que cette structure exige.
Une interface de forme peut exiger un nom et une méthode d’aire sans fournir l’implémentation de la classe.
Interface publique
Une interface publique est l’ensemble des opérations accessibles par lesquelles un autre code utilise un objet sans dépendre de son stockage interne.
Les appelants peuvent définir une consigne de thermostat même si la classe change ultérieurement la façon dont elle la stocke.

L

Liaison dynamique
Une liaison dynamique relie un nom importé à la valeur actuelle du module exportateur, de sorte que les modifications de ce module restent visibles pour les fichiers importateurs.
Lorsqu’un module exporte un compteur et une fonction d’incrémentation, un fichier importateur lit le compteur mis à jour par son nom importé après l’exécution de l’incrémentation.
Linter
Un linter analyse le code source selon des règles configurées pour signaler les bogues probables ou les constructions risquées sans exécuter le programme.
ESLint peut détecter une variable renvoyée mal orthographiée même lorsqu’aucun test n’appelle la fonction qui la contient.

M

Masquage
Le masquage se produit lorsqu’une propriété propre cache une propriété héritée de même nom pendant la recherche ordinaire d’une propriété.
Supprimer la taille de police propre d’un objet peut rendre de nouveau visible la taille par défaut inchangée sur son prototype.
Membre statique
Un membre statique est un champ ou une méthode qui appartient à la classe elle-même et auquel on accède par la classe plutôt que par une instance individuelle.
Un compteur de constructions partagé se lit sur la classe, tandis que chaque objet conserve ses propres données d’instance.
Méta-framework
Un méta-framework ajoute des fonctionnalités d’application plus larges autour d’un écosystème d’interface utilisateur, comprenant couramment le routage, le rendu sur le serveur et une configuration de compilation.
Un projet peut choisir une telle couche lorsqu’il a besoin à la fois de navigation entre pages et de vues rendues sur le serveur.
Méthode
Une méthode est une fonction fournie dans l’interface d’un objet ou d’une classe, qui agit généralement sur l’objet recevant l’appel.
L’appel tile.area() permet à la méthode de lire les dimensions de tile par l’intermédiaire de l’objet receveur this.
Méthode de fabrique statique
Une méthode de fabrique statique est une méthode de classe qui crée et renvoie des instances sous un nom décrivant un choix de construction particulier.
Une classe de rectangle peut proposer Rectangle.square(5) pour créer une instance dont les côtés sont de même longueur.
Méthode privée
Une méthode privée est un comportement interne à une classe dont le nom commence par # et qui garde les opérations auxiliaires hors de l’interface publique de l’objet.
Une classe peut appeler this.#check(value) pour valider une entrée sans exposer cette fonction auxiliaire au code extérieur.
Minification
La minification réduit la taille du code généré en supprimant les éléments de mise en forme inutiles et en raccourcissant les noms pris en charge, sans modifier le comportement voulu.
Une ressource de production peut avoir des noms locaux plus courts même si ses sources utilisaient des identifiants descriptifs.
Mixin
Un mixin est une collection réutilisable de méthodes copiées dans une classe ou sur un prototype pour ajouter des comportements sans choisir une autre superclasse.
Un mixin de sérialisation peut fournir des méthodes auxiliaires à des classes sans autre lien par l’intermédiaire de leurs prototypes.
Module ES
Un module ES est un module JavaScript qui utilise la syntaxe standard import et export, avec sa propre portée et des règles d’exécution strictes.
Un module de formes peut importer des fonctions utilitaires de géométrie sans placer leurs noms dans la portée globale de la page.

N

Niveau de sévérité d’une règle
Le niveau de sévérité d’une règle détermine si une règle du linter est désactivée, signale un avertissement ou signale une erreur qui fait normalement échouer la commande.
Un avertissement de variable inutilisée peut apparaître lors d’une exécution réussie, tandis qu’une erreur de nom non défini la fait échouer.
npm
npm est le gestionnaire de paquets fourni avec Node.js, composé d’un outil en ligne de commande et d’un registre public de paquets associé.
Un projet utilise npm pour installer les dépendances et exécuter les commandes enregistrées dans ses scripts de paquet.
npx
npx est un exécuteur de commandes qui peut utiliser un exécutable de paquet installé ou proposer de télécharger et d’exécuter temporairement une commande de paquet.
Une personne peut essayer une commande de serveur statique sans l’ajouter comme dépendance permanente du projet.

O

Objet receveur
Un objet receveur est l’objet sur lequel une méthode est appelée ; il fournit normalement la valeur de this lors d’un appel de méthode ordinaire.
Dans box.open(), l’objet receveur est box ; détacher open ne lie pas définitivement cet objet receveur.

P

Paquet
Un paquet est un dossier décrit par un fichier package.json, qui enregistre son identité et peut décrire des scripts et des dépendances.
Une application locale peut être un paquet npm même lorsque son indicateur private empêche sa publication dans le registre.
Plage de versions
Une plage de versions décrit les versions autorisées par une entrée de dépendance ; elle peut être plus large que la version exacte actuellement installée.
Une plage avec accent circonflexe peut autoriser une version mineure plus récente alors qu’une installation propre suit toujours un choix verrouillé plus ancien.
Polymorphisme
Le polymorphisme permet à un même appel de méthode de sélectionner différentes implémentations pour différents objets receveurs au moyen d’une interface commune.
Une boucle appelle describe() sur des cercles et des rectangles, et chaque objet fournit l’aire appropriée.
Préparer, agir, vérifier
Préparer, agir, vérifier est une structure de test qui consiste à préparer les entrées, exécuter le comportement et comparer le résultat à une attente.
Un test construit un rectangle, appelle sa méthode d’aire, puis vérifie un résultat calculé indépendamment.
Propriété énumérable
Une propriété énumérable possède un indicateur qui lui permet d’apparaître dans les opérations d’énumération qui sélectionnent les clés énumérables.
Object.keys énumère les clés de type chaîne propres et énumérables, tandis que for...in peut aussi inclure celles qui sont héritées.
Propriété héritée
Une propriété héritée est trouvée dans la chaîne de prototypes d’un objet plutôt que stockée comme propriété propre sur cet objet.
Un objet de paramètres peut lire un thème par défaut alors que Object.hasOwn indique qu’il n’a pas de clé de thème propre.
Propriété propre
Une propriété propre est stockée directement sur un objet, contrairement à une propriété héritée disponible par l’un de ses liens de prototype.
La largeur d’un rectangle peut être une propriété propre même si sa méthode d’aire ordinaire est héritée.
Prototype
Un prototype est un objet, ou null, lié à un autre objet et consulté lorsque celui-ci ne possède pas lui-même une propriété demandée.
Une instance peut trouver une méthode d’aire partagée sur le prototype de sa classe sans stocker sa propre copie de la méthode.

R

Redéfinition de méthode
Une redéfinition de méthode est une méthode de sous-classe qui remplace une méthode héritée de même nom pour les appels qui sélectionnent le comportement de cette sous-classe.
Un cercle redéfinit area() tout en continuant à hériter de la méthode de description partagée de la classe parente.
Réexportation
Une réexportation transmet les exportations d’un autre module par l’intermédiaire du module courant, ce qui permet à un fichier de regrouper une interface publique.
L’index d’un dossier peut transmettre des fonctions utilitaires nommées ; une déclaration d’exportation avec astérisque ne transmet pas leur exportation par défaut.
Remplacement de modules à chaud
Le remplacement de modules à chaud met à jour un module modifié dans une application en cours d’exécution, en conservant souvent l’état lorsque cette mise à jour le permet, sans rechargement complet de la page.
La modification d’un composant peut mettre à jour son comportement affiché tout en gardant intact l’état actuel de l’interface.

S

Script différé
Un script différé attend la fin de l’analyse du HTML avant de s’exécuter ; les scripts de module ordinaires du navigateur ont ce comportement par défaut.
Un module d’entrée ordinaire peut attacher des gestionnaires aux éléments apparus plus haut dans la page HTML analysée.
Script npm
Un script npm est une commande nommée dans package.json qui donne à une tâche du projet un point d’entrée reproductible par la ligne de commande npm.
Le script lint peut exécuter l’outil installé localement dans le projet lorsqu’un membre de l’équipe lance npm run lint.
Serveur de développement
Un serveur de développement sert localement un projet pendant les modifications et peut résoudre les importations, transformer les sources et mettre la page à jour lorsque les fichiers changent.
Un serveur de développement Vite affiche une adresse HTTP locale par laquelle le navigateur charge l’application en cours de développement.
Sous-classe
Une sous-classe est une classe déclarée avec extends qui hérite d’une superclasse et peut ajouter des membres ou spécialiser des comportements hérités.
Une sous-classe de carré peut transmettre deux fois la même longueur de côté au constructeur de sa classe parente rectangle.
Spécificateur de module
Un spécificateur de module est la chaîne qui identifie le module demandé par une importation, comme un chemin relatif, une URL ou un nom de paquet.
Le spécificateur "../utils.js" demande au système de chargement un module situé dans le dossier parent du fichier importateur.
Spécificateur nu
Un spécificateur nu nomme un paquet sans préfixe de chemin ni URL complète, ce qui oblige l’environnement ou les outils à résoudre ce nom.
Node.js peut résoudre un nom de paquet installé qu’un navigateur seul ne peut pas trouver sans correspondance supplémentaire.
Superclasse
Une superclasse est la classe parente dont hérite une sous-classe ; elle fournit une initialisation et des comportements accessibles aux instances dérivées.
La superclasse des formes stocke le nom commun utilisé lorsque ses sous-classes produisent leurs descriptions.

T

Test aux limites
Un test aux limites vérifie le comportement à une borne exacte ou juste au-delà, afin de révéler les erreurs de comparaison inclusive ou exclusive.
Un intervalle de consigne de 10 à 30 °C nécessite des vérifications aux deux bornes et pour des valeurs juste à l’extérieur de chaque borne autorisée.
Test unitaire
Un test unitaire exécute une petite partie d’un programme avec des entrées contrôlées et vérifie que son comportement observé correspond à un résultat attendu.
Un test de rectangle peut vérifier une aire connue sans charger la page qui affiche le rectangle.
Tolérance
Une tolérance est une différence numérique autorisée pour comparer des résultats approchés sans accepter d’erreurs au-delà de la borne choisie.
Un test en virgule flottante peut accepter une infime différence d’arrondi tout en rejetant une formule d’aire incorrecte.
Tree shaking
Le tree shaking supprime le code que l’analyse de compilation peut prouver inutilisé et supprimer sans risque, tout en conservant les effets de bord qui doivent s’exécuter.
Une fonction utilitaire pure inutilisée peut disparaître des résultats alors qu’une autre fonction utilitaire du même module reste présente.
TypeScript
TypeScript ajoute à JavaScript une syntaxe de types statiques et leur vérification afin de détecter les utilisations incompatibles des valeurs avant l’exécution.
Le vérificateur peut signaler une chaîne transmise à un paramètre déclaré numérique même si JavaScript pourrait la convertir implicitement.

V

Validation à l’exécution
La validation à l’exécution vérifie les valeurs réelles pendant que le programme s’exécute, notamment les données provenant de sources externes que les types ne peuvent pas examiner.
Des données réseau analysées nécessitent un contrôle avant qu’un champ déclaré numérique soit utilisé dans un calcul.
Versionnement sémantique
Le versionnement sémantique note les versions publiées sous la forme MAJEURE.MINEURE.CORRECTIF pour distinguer les changements incompatibles, les fonctionnalités compatibles et les corrections compatibles.
Une version stable qui ajoute une fonctionnalité compatible passe de 2.4.1 à 2.5.0 au lieu de passer à une nouvelle version majeure.

À propos de cette unité

Par StudeliSignaler une erreur

Crée ton propre Matériel d'Étude

Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.

Commencer