Klassen en modules in JavaScript met ontwikkelaarstools

Leer hoe professionele JavaScript-projecten zijn opgebouwd. Bouw objecten met klassen, privévelden en overerving en bekijk de prototypeketen waarop klassen zijn gebaseerd. Deel code op in ES-modules die in de browser en in Node.js werken, beheer pakketten met npm en package.json en gebruik de dagelijkse hulpmiddelen van een moderne werkwijze: een linter en codeopmaker, een ontwikkelserver en bundler en een testrunner. Bekijk tot slot welke plaats TypeScript en front-endframeworks in die gereedschapsketen innemen.

BeginnerLes 9 van 9 in Cursus JavaScript programmeren: DOM, events, asynchrone code en modules

Wat je leert

  1. Gebruik klassen om objecten met gedeeld gedrag te maken, bescherm hun gegevens, bouw hiërarchieën met overerving en leg de prototypeketen uit waarop klassen zijn gebaseerd.
    • Definieer een klasse en maak objecten met new
      Schrijf een klasse met een constructor, velden, methoden, getters en setters, maak instanties met new en zorg dat this naar het juiste object blijft verwijzen.
    • Bescherm gegevens met privéleden en deel waarden met statische leden
      Verberg de interne toestand van een object achter privévelden en privémethoden en plaats waarden en hulpfuncties die bij de klasse als geheel horen in statische leden.
    • Bouw klassenhiërarchieën met extends en super
      Maak subklassen die gedrag overerven en overschrijven, roep de ouderklasse aan met super, controleer typen met instanceof en bepaal wanneer overerving of compositie beter past.
    • Leg uit welke rol prototypes spelen bij objecten en klassen
      Beschrijf hoe JavaScript eigenschappen via de prototypeketen vindt, hoe klassen en extends die keten opzetten en waarom ingebouwde prototypes ongewijzigd blijven.
  2. Deel een programma op in modules die functionaliteit exporteren en importeren, voer ze uit in browsers en Node.js, laad code wanneer je die nodig hebt en geef elke module één duidelijke taak.
    • Exporteer en importeer code tussen bestanden
      Deel een programma op in ES-modules en verbind ze met benoemde en standaardexports, hernoemde imports, naamruimte-imports en herexports. Weet daarbij hoe modulebereik en actuele bindingen werken.
    • Voer modules uit in de browser en in Node.js
      Laad modules op een webpagina met type="module" vanaf een lokale server, los modulepaden en namen zonder pad op en begrijp hoe Node.js tussen ES-modules en CommonJS kiest.
    • Laad modules wanneer je ze nodig hebt en deel een project in modules in
      Gebruik dynamische import() en await op moduleniveau, deel een applicatie op in modules met een duidelijke taak en voorkom problemen met neveneffecten en circulaire imports.
  3. Beschrijf een project in package.json, voer de taken uit met npm-scripts en installeer, werk afhankelijkheden bij en kies ze zo dat elke computer dezelfde werkende verzameling pakketten krijgt.
    • Zet een project op met npm en package.json
      Maak een project met npm init, lees en bewerk de hoofdvelden van package.json, voer taken uit met npm-scripts en npx en lees semantische versienummers.
    • Installeer afhankelijkheden, werk ze bij en kies geschikte afhankelijkheden
      Installeer pakketten als uitvoerings- of ontwikkelafhankelijkheden, lees versiebereiken, gebruik package-lock.json en npm ci voor herhaalbare installaties, houd afhankelijkheden bijgewerkt en kies pakketten veilig.
  4. Gebruik een linter en een codeopmaker om problemen op te sporen en een consistente stijl te behouden, een ontwikkelserver en bundler om een project uit te voeren en uit te brengen en een testrunner om te controleren of de code werkt.
    • Spoor problemen op met een linter en maak code automatisch op
      Gebruik ESLint om waarschijnlijke fouten te vinden zonder de code uit te voeren en Prettier om een consistente opmaak te behouden. Configureer beide en voer ze uit vanuit scripts en de editor.
    • Maak een project beschikbaar via een ontwikkelserver en bundel het met een bundler
      Leg uit wat bundlers en ontwikkelservers doen, doorloop met Vite de cyclus van ontwikkelen, bouwen en vooraf bekijken en begrijp verwijdering van ongebruikte code, minificatie, bestandsnamen met hashes, sourcemaps en omgevingsvariabelen.
    • Controleer code automatisch met een testrunner
      Schrijf unittests met asserties voor functies en klassen, voer ze uit met de ingebouwde testrunner van Node.js of met Vitest, lees foutmeldingen en ontwerp code die gemakkelijk te testen is.
  5. Leg uit wat TypeScript en front-endframeworks aan JavaScript toevoegen, hoe ze modules, npm en buildtools gebruiken en hoe alle hulpmiddelen in een project samenwerken.
    • Leg uit wat TypeScript aan JavaScript toevoegt
      Beschrijf hoe de statische typen van TypeScript fouten opsporen voordat code wordt uitgevoerd, hoe TypeScript-code JavaScript wordt en wanneer de extra stap de moeite waard is.
    • Plaats frameworks binnen een complete moderne gereedschapsketen
      Leg uit wat front-endframeworks doen en hoe ze voortbouwen op modules, npm en bundlers, en voeg de hulpmiddelen uit dit onderdeel samen tot één dagelijkse werkwijze.

Klassen en modules in JavaScript: uitleg

5 hoofdstukken

1

Bouw objecten die gedrag delen

Een gewoon object groepeert bij elkaar horende waarden. Een klasse voegt een herhaalbare manier toe om objecten met eigen gegevens en gedeeld gedrag te maken. Begin met constructors en methoden en beheers daarna wijzigingen via privévelden en een publieke interface. Met overerving kunnen verwante klassen dat gedrag specialiseren. De prototypeketen verklaart hoe JavaScript de methoden vindt en waarom een instantie code kan gebruiken die ergens anders is opgeslagen.

1.1 Maak en gebruik instanties van klassen

Een klasse beschrijft objecten met dezelfde structuur en hetzelfde gedrag. Elk object dat op basis van de klasse wordt gemaakt, is een instantie. Gebruik een klasse wanneer meerdere objecten dezelfde bewerkingen nodig hebben; voor één instellingenwaarde is een gewoon object vaak genoeg.

Geef elk object eigen gegevens

Klassenamen gebruiken volgens afspraak PascalCase, zoals Rectangle. De constructor wordt telkens uitgevoerd wanneer new een instantie maakt. Daarbinnen verwijst this naar het nieuwe object. Een toewijzing aan this.width slaat een instantie-eigenschap op; een parameter met alleen de naam width is een lokale variabele.

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

Bij a.area() roept JavaScript de methode aan met this ingesteld op a. De breedte van 3 cm vermenigvuldigd met de hoogte van 4 cm geeft 12 cm². Voor de omtrek tel je de twee verschillende zijden op en verdubbel je die som, wat 14 cm geeft. Als je b.width wijzigt, verandert alleen b.

Methoden hebben geen sleutelwoord function en geen komma's ertussen. Een klasse heeft hoogstens één constructor. Als je die bij een klasse zonder extends weglaat, krijgt de klasse een lege standaardconstructor. new geeft de gemaakte instantie automatisch terug.

Een veld declareert een eigenschap in het klassenlichaam: unit = "cm"; geeft elke instantie een eigen waarde. label; begint als undefined. In een klasse zonder extends worden instantievelden geïnitialiseerd voordat het constructorlichaam wordt uitgevoerd.

Lees en wijs toe via getters en setters

Een getter wordt uitgevoerd wanneer een eigenschap wordt gelezen. Bij get area() { return this.width * this.height; } lees je a.area zonder haakjes. Dit is een alternatief voor de methode hierboven, die a.area() gebruikt.

Een setter wordt uitgevoerd bij een toewijzing en kan ongeldige invoer afwijzen. Een setter heeft aparte opslag nodig: set width(value) { this.width = value; } roept zichzelf herhaaldelijk aan totdat de aanroepstapel overloopt. Sla de waarde onder een andere naam op, zoals het privéveld #width.

Behoud het ontvangende object wanneer je een methode doorgeeft
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

Klassenmethoden worden in strikte modus uitgevoerd. Een losgekoppelde aanroep heeft geen ontvangend object vóór de punt, dus is this gelijk aan undefined. De aanroeper van een callback kan ook een ander ontvangend object meegeven. Een omhullende pijlfunctie behoudt de aanroep op counter; counter.increment.bind(counter) maakt een gebonden functie. Een veld met een pijlfunctie, increment = () => { this.count++; };, legt ook de this van de instantie vast.

Rectangle(3, 4) aanroepen zonder new werpt een TypeError op. Een klasse gebruiken voordat de declaratie ervan is geïnitialiseerd, werpt een ReferenceError op. Klassen verschillen hierin van functiedeclaraties die eerder in een bestand kunnen worden aangeroepen.

JSON bewaart gegevens, geen klassegedrag. JSON.stringify(a) slaat de eigen publieke breedte en hoogte op. Bij het ontleden van die tekst ontstaat een gewoon object; maak opnieuw een instantie met new Rectangle(data.width, data.height) om de methoden te gebruiken.

Belangrijkste punten

  • new maakt een instantie en voert de constructor uit; this duidt het ontvangende object van een methodeaanroep aan.
  • Velden bevatten de gegevens van elke instantie; gewone methoden worden gedeeld.
  • Getters lees je als eigenschappen; setters worden uitgevoerd bij een toewijzing en hebben aparte opslag nodig.
  • Gebruik een omhullende pijlfunctie of een gebonden functie wanneer een callback het ontvangende object moet behouden.
  • JSON herstelt geen klassenmethoden bij het ontleden van opgeslagen gegevens.

1.2 Bewaak toestand met privévelden

Een object kan een kleine publieke interface aanbieden en de opslag tegelijk privé houden. Dit is inkapseling. De interface bepaalt welke wijzigingen geldig zijn; afscherming alleen controleert geen waarde die aan een publieke setter wordt doorgegeven.

Valideer aan de grens

Een privéveld begint met # en moet in het klassenlichaam worden gedeclareerd. Code binnen die klasse leest het via this.#target. Code buiten de klasse kan t.#target niet lezen of beschrijven: dat is een syntaxisfout, geen leesactie die undefined teruggeeft.

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

De getter maakt de waarde leesbaar zonder toegang tot de opslag te geven. De setter wijst eerst invoer af die geen eindig getal is en daarna waarden buiten het bereik van 10 tot en met 30 °C. Alleen een geaccepteerde waarde bereikt de toewijzing. Na een afgewezen poging om 35 °C in te stellen, blijft de doelwaarde 22 °C. Een numerieke string zoals "22" komt ook niet door Number.isFinite.

De getter en setter gebruiken #target, dus het toewijzen aan t.target roept de setter niet recursief aan. De namen target en #target zijn verschillend. Een onderstrepingsteken aan het begin, zoals in _target, vraagt andere programmeurs alleen om een publieke eigenschap als intern te behandelen; JavaScript staat toegang ertoe nog steeds toe.

Privévelden verschijnen niet in Object.keys, for...in of JSON-serialisatie. Deze thermostaat heeft geen eigen publieke velden, dus geeft JSON.stringify(t) de tekst "{}". Om een object op te slaan, kan daarom een expliciete publieke methode nodig zijn die de op te slaan gegevens teruggeeft.

Houd interne hulpmethoden privé

Een methode zoals #check(value) { ... } kan validatiestappen bevatten en wordt binnen de klasse aangeroepen als this.#check(value). De methode maakt geen deel uit van de publieke interface. Binnen de klasse controleert #target in obj of een object dat privéveld heeft.

Een subklasse kan de privénaam van de ouderklasse niet rechtstreeks gebruiken. De subklasse kan wel de publieke getter of setter van de ouderklasse gebruiken, die wordt uitgevoerd in de klasse die het veld heeft gedeclareerd. Zo houdt de ouderklasse controle over haar eigen toestand.

Plaats gedeeld werk op de klasse

Een statisch lid hoort bij de klasse. Thermostat.MIN is 10, terwijl t.MIN gelijk is aan undefined. Deze statische grenzen zijn publieke velden; static maakt ze op zichzelf niet alleen-lezen.

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

Elke constructor verhoogt één teller op klasseniveau. Een instantieveld zou elk object daarentegen een aparte teller geven. Een statische fabrieksmethode, zoals static square(side) { return new Rectangle(side, side); }, hoort binnen Rectangle en wordt aangeroepen als Rectangle.square(5). Een statische vergelijkingsfunctie kan aan sort worden doorgegeven wanneer die de te vergelijken objecten als argumenten ontvangt.

Binnen een statische methode is this de klasse waarop de methode is aangeroepen; het is geen instantie van een rechthoek met een breedte. Een initialisatieblok static { ... } voert de initialisatie één keer uit wanneer de klasse wordt gedefinieerd en heeft toegang tot de privéleden van die klasse.

Belangrijkste punten

  • Privévelden met # worden door JavaScript afgedwongen; een onderstrepingsteken is alleen een conventie.
  • Valideer via de publieke interface voordat je de privétoestand wijzigt.
  • Privévelden ontbreken bij gewone opsomming van sleutels en bij JSON-serialisatie.
  • Subklassen gebruiken de publieke interface van de ouderklasse om met haar privétoestand te werken.
  • Roep statische leden aan op de klasse; ze bevatten niet de gegevens van elke instantie.
  • Een statisch initialisatieblok wordt één keer uitgevoerd wanneer de klasse wordt gedefinieerd.

1.3 Specialiseer een klasse met overerving

Overerving modelleert een “is een”-relatie. Een cirkel is een vorm, dus kan een klasse Circle de gedeelde beschrijving van een vorm overerven en tegelijk een eigen oppervlakteberekening aanbieden. Een subklasse erft gedrag over zonder elke methode naar haar eigen lichaam te kopiëren.

Initialiseer eerst de ouderklasse

class Circle extends Shape maakt Circle een subklasse en Shape haar superklasse. In een constructor van een subklasse roept super(...) de constructor van de ouderklasse aan. Die aanroep moet worden uitgevoerd voordat this voor het eerst wordt gebruikt. Een subklasse zonder constructor krijgt er een die haar argumenten doorgeeft aan de ouderklasse.

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; }
}

De aanroep new Circle(2).describe() geeft "Circle with area 12.57 cm²". Eerst stelt super de naam in. De cirkel slaat zijn straal op. De overgeërfde methode describe() roept vervolgens this.area() aan, waarmee de methode van de cirkel wordt gevonden. toFixed(2) maakt het resultaat op voor weergave. new Rectangle(3, 4).describe() geeft "Rectangle with area 12.00 cm²".

Overschrijf of breid een methode uit

Een subklasse overschrijft een methode door dezelfde naam te declareren. Zij kan de versie van de ouderklasse aanroepen via 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) initialiseert gelijke waarden voor breedte en hoogte. De overgeërfde oppervlaktemethode vermenigvuldigt die en de overschreven methode voegt informatie toe aan de overgeërfde beschrijving. Als je vereiste argumenten voor de ouderklasse vergeet, kunnen haar eigenschappen undefined blijven; super() aanroepen is niet genoeg als de ouderklasse waarden nodig heeft.

Polymorfisme betekent dat dezelfde aanroep verschillend gedrag kan selecteren. Een lus kan s.describe() aanroepen op cirkels en rechthoeken; elke beschrijving roept de juiste area() aan. Als je een vorm met een eigen oppervlaktemethode toevoegt, is er geen nieuw geval in die lus nodig.

new Circle(2) instanceof Circle en new Circle(2) instanceof Shape zijn allebei waar. Statische leden worden ook overgeërfd. De relatie van een instantie met een klasse volgt uit haar prototypeketen; dat is wat instanceof normaal controleert.

Kies een bruikbare relatie

Een klasse kan slechts één ouderklasse uitbreiden. Gebruik voor een “heeft een”-relatie compositie: een auto heeft een motor en vraagt this.engine.start() om werk te doen. Alleen een hulpmethode delen is geen reden om te stellen dat een niet-verwante klasse een soort van de andere is. Een mixin kopieert een groep methoden naar een prototype, bijvoorbeeld met Object.assign(Rectangle.prototype, serializable). Diepe ketens van ouderklassen kunnen wijzigingen moeilijk te volgen maken.

Ook ingebouwde klassen kunnen worden uitgebreid. Een constructor van ValidationError extends Error roept super(message) aan, stelt this.name = "ValidationError" in en kan this.field = field opslaan. Een catch-blok kan err instanceof ValidationError gebruiken om die fout anders af te handelen en het overgeërfde bericht te lezen.

Belangrijkste punten

  • Gebruik extends voor een “is een”-relatie en compositie voor een “heeft een”-relatie.
  • Roep super(...) aan met de argumenten die de ouderklasse nodig heeft voordat je this gebruikt.
  • Een overschreven methode kan gedrag van de ouderklasse hergebruiken met super.methodName().
  • Dankzij polymorfisme kan één methodeaanroep werken op verwante klassen.

1.4 Volg hoe eigenschappen via prototypes worden opgezocht

Een object heeft een verborgen verwijzing naar een ander object, zijn prototype, of naar null. Als een eigenschap ontbreekt, wordt bij het lezen die verwijzing gevolgd. JavaScript blijft zoeken totdat het de eigenschap vindt of null bereikt; een zoekactie zonder resultaat geeft undefined terug.

Onderscheid opgeslagen en overgeërfde waarden
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) maakt een leeg object met defaults als prototype. Door een waarde aan fontSize toe te wijzen, maak je een eigen eigenschap die de overgeërfde waarde overschaduwt. Daarbij blijft defaults.fontSize ongewijzigd. Na delete settings.fontSize bereikt de zoekactie weer de overgeërfde waarde 16.

ControleEigenschappen die worden meegenomen
Object.hasOwn(obj, key)Eigen eigenschappen, opsombaar of niet
Object.keys(obj)Eigen opsombare stringsleutels
key in objEigen en overgeërfde eigenschappen, opsombaar of niet
for...inOpsombare stringsleutels, inclusief overgeërfde

Een ontbrekende eigen eigenschap kan nog steeds in de keten bestaan. Klassenmethoden zijn niet opsombaar, dus vermeldt for...in ze normaal gesproken niet. Gebruik Object.getPrototypeOf(settings) om het prototype te lezen. Geef de voorkeur aan deze Object-methoden boven de oudere accessor __proto__.

Bekijk hoe klassen methoden delen

Voor een rechthoekinstantie r is Object.getPrototypeOf(r) === Rectangle.prototype waar. De breedte is een eigen eigenschap, terwijl area normaal op Rectangle.prototype is opgeslagen. Object.hasOwn(r, "area") is onwaar, hoewel r.area() werkt. Een veld met een pijlfunctie is anders: dat maakt op elke instantie een eigen functie-eigenschap.

Een overgeërfde methode ontvangt nog steeds het object vóór de punt als this. De gedeelde oppervlaktemethode kan daardoor voor elke rechthoek andere afmetingen lezen zonder op elk object een aparte methode op te slaan.

Voor de vormenhiërarchie verloopt het opzoeken als volgt:

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

De oppervlaktemethode van de cirkel wordt als eerste gevonden. De beschrijving komt van Shape.prototype en toString kan van Object.prototype komen. Shape.prototype in de keten verklaart ook waarom circle instanceof Shape waar is.

De naam Rectangle.prototype betekent het prototype dat aan rechthoekinstanties wordt gegeven. De naam duidt niet het verborgen prototype van de functie Rectangle zelf aan; voor deze klasse is dat Shape wanneer zij Shape uitbreidt, of Function.prototype voor een klasse zonder superklasse.

Herken oudere constructorcode
function Rectangle(width, height) {
  this.width = width;
  this.height = height;
}
Rectangle.prototype.area = function () {
  return this.width * this.height;
};

Constructorfuncties gebruiken dezelfde basisstructuur tussen instantie en prototype. Klassensyntaxis voegt regels toe: new is vereist, het lichaam is strikt, methoden zijn niet opsombaar en privéleden zijn beschikbaar. typeof Rectangle is bij beide vormen "function".

Arrays vinden map op Array.prototype; stringmethoden komen van String.prototype. Voeg geen eigen methoden toe aan ingebouwde prototypes: bibliotheken en toekomstige standaarden kunnen dezelfde namen voor ander gedrag gebruiken. Het bestaande gebruik van flatten door een bibliotheek heeft ertoe bijgedragen dat de standaardarraymethode flat werd genoemd.

Een gewone toewijzing aan een gegevenseigenschap maakt of wijzigt een eigen eigenschap, maar een overgeërfde setter kan de toewijzing onderscheppen. Het prototype van een bestaand object wijzigen met Object.setPrototypeOf is toegestaan maar kan de prestaties schaden; kies het prototype wanneer je het object maakt.

Belangrijkste punten

  • Bij het lezen van een eigenschap worden het object, zijn prototypes en ten slotte null doorzocht.
  • Een eigen eigenschap kan een overgeërfde waarde overschaduwen zonder het prototype te wijzigen.
  • Of een eigenschap eigen is en of die opsombaar is, zijn verschillende vragen.
  • Gewone klassenmethoden staan op het prototype van de instantie en delen gedrag.
  • Een overgeërfde methode gebruikt de ontvangende instantie als this.
  • Constructorfuncties en klassen bouwen op hetzelfde prototypemechanisme.
  • Laat ingebouwde prototypes ongewijzigd om conflicten in namen en gedrag te voorkomen.
2

Verbind bestanden met ES-modules

Met modules kan een programma groeien tot meer dan één script, terwijl elk bestand begrijpelijk blijft. Exports beschrijven wat een bestand aanbiedt en imports tonen wat het nodig heeft. Leer hoe die verbinding werkt, hoe browsers en Node.js modules laden en hoe je een functie alleen laadt wanneer erom wordt gevraagd. Duidelijke grenzen tussen gegevens, opslag en het bijwerken van de pagina maken code ook gemakkelijker te testen en helpen circulaire afhankelijkheden voorkomen.

2.1 Exporteer functionaliteit en importeer de bindingen

Een ES-module heeft een eigen bereik. Declaraties op het hoogste niveau blijven binnen het bestand, tenzij ze worden geëxporteerd. Importeurs vragen specifieke functionaliteit op, waardoor afhankelijkheden zichtbaar worden zonder alles in globale variabelen te plaatsen.

Gebruik de juiste import bij de export
// 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

De startmodule importeert één klasse. De module van de klasse importeert twee hulpfuncties. Bij een straal van 3 cm is de oppervlakte ongeveer 28,274 cm²; de afrondingsfunctie geeft 28,27. De startmodule krijgt niet automatisch toegang tot de hulpfuncties die binnen een andere module worden gebruikt.

ExportBijbehorende import
export const MAX = 30;import { MAX } from "./limits.js";
export default class Circle {}import Circle from "./shapes.js";
Een standaardexport plus de benoemde export round2import Circle, { round2 } from "./shapes.js";

Een module kan veel benoemde exports hebben, maar hoogstens één standaardexport. Benoemde imports gebruiken de geëxporteerde naam tussen accolades; de lokale naam voor een standaardimport wordt door de importeur gekozen. Met import { Circle } vraag je de standaardexport niet op, ook niet als de geëxporteerde klasse Circle heet.

Hernoem, groepeer en herexporteer

import { circleArea as areaOfCircle } from "./geometry.js"; geeft geïmporteerde functionaliteit een andere lokale naam. export { circleArea as area }; wijzigt de geëxporteerde naam. Een exportlijst kan ook declaraties beschikbaar maken die eerder in het bestand zijn gedaan.

import * as geometry from "./geometry.js"; maakt een modulenaamruimteobject. Roep geometry.circleArea(3) aan. Een naamruimte bevat een standaardexport onder de eigenschap default als de module er een heeft.

Een bestand kan exports van andere bestanden verzamelen: export { circleArea } from "./geometry.js"; geeft een benoemde export door. export * from "./geometry.js"; geeft benoemde exports door, maar niet de standaardexport van die module.

Begrijp gedeelde uitvoering en actuele bindingen

Modules worden in strikte modus uitgevoerd en hebben undefined als this op het hoogste niveau. Afhankelijkheden worden uitgevoerd vóór het eigen lichaam van de importerende module. Als verschillende bestanden dezelfde opgeloste module importeren, hergebruiken ze één uitgevoerde module en haar toestand.

Stel dat een module let count = 0 exporteert en increment() die waarde wijzigt. Nadat een importeur increment() heeft aangeroepen, geeft de geïmporteerde count bij het lezen 1. Imports zijn actuele bindingen, geen momentopnamen. De importeur kan de binding zelf niet opnieuw toewijzen. Als een export een object is, kun je nog wel een eigenschap van dat object wijzigen en zien andere importeurs die wijziging.

Houd statische importdeclaraties op het hoogste niveau van een module. Een statische import binnen een if of functie is een syntaxisfout; dynamische import() verzorgt het later laden. Neem .js op in relatieve ES-modulepaden voor browsers en Node.js: deze laders voegen de extensie niet toe. Een padfout of een onjuiste combinatie van benoemde import en standaardimport verhindert dat de module wordt geladen. Herstel daarom de import voordat je een fout zoekt in de code die daarna had moeten worden uitgevoerd.

Belangrijkste punten

  • Modules houden declaraties op het hoogste niveau lokaal, tenzij ze worden geëxporteerd.
  • Benoemde imports gebruiken accolades; een standaardimport gebruikt geen accolades.
  • Een naamruimte groepeert exports, terwijl herexports de interface van een module doorgeven.
  • Imports zijn actuele, alleen-lezen bindingen aan gedeelde moduletoestand.
  • Statische imports horen op het hoogste niveau en relatieve ES-modulepaden hebben extensies nodig.

2.2 Laad modules in browsers en Node.js

Dezelfde ES-modulesyntaxis werkt in een browser en in Node.js. Elke omgeving moet nog steeds weten dat een bestand een module is en heeft een eigen manier om de gevraagde paden op te lossen.

Start een browsermodule
<script type="module" src="main.js"></script>

Laad alleen de startmodule met een scripttag. De imports halen de andere bestanden automatisch op. Modulescripts zonder async worden uitgesteld: ze worden uitgevoerd nadat de HTML is ontleed, in documentvolgorde. De pagina-elementen die ze gebruiken, zijn dan beschikbaar.

Maak de map via HTTP beschikbaar met een lokale server, zoals python3 -m http.server of npx serve, en open het localhostadres ervan. Als je de HTML vanaf schijf opent, mislukken moduleverzoeken meestal door de beveiligingsregels van de browser. De server moet JavaScript ook teruggeven met een geschikt MIME-type, zoals text/javascript.

Moduledeclaraties worden geen globale variabelen. Een inline eventhandler zoals onclick="save()" kan een functie die lokaal is voor een module niet vinden. Koppel de eventhandler in plaats daarvan vanuit JavaScript:

const button = document.querySelector("#save");
function save() { console.log("Saved"); }
button.addEventListener("click", save);
Los paden en pakketnamen op

De moduleaanduiding is de string die de module aanduidt. ./geometry.js is relatief ten opzichte van het importerende bestand; ../geometry.js gaat één map omhoog. Een pad dat met / begint, start bij de hoofdmap van de website, terwijl een volledige HTTPS-URL de complete locatie aangeeft.

Een naam zonder pad, zoals "date-fns", heeft geen padvoorvoegsel. Een browser kan er niet naar zoeken in node_modules. Een importmap vóór de modulescripts koppelt zo'n naam aan een URL. Een ontwikkelserver of bundler kan in plaats daarvan geïnstalleerde pakketten oplossen en voorbereiden voor de browser. Alleen een pakket installeren verandert de lader van de browser niet.

Maak het moduleformaat van Node.js expliciet
Bestand of instellingNode.js-formaat
.mjsES-module
.cjsCommonJS
.js onder "type": "module"ES-module
.js onder "type": "commonjs"CommonJS

Node.js leest type uit de dichtstbijzijnde package.json in een bovenliggende map. Zonder expliciet type kunnen huidige versies ES-modulesyntaxis herkennen in een verder dubbelzinnig .js-bestand. Stel "type": "module" in een nieuw ES-moduleproject in, zodat hulpmiddelen het eens zijn over het bedoelde formaat. De extensies .mjs en .cjs gaan boven die instelling.

Met de drie bestanden uit het cirkelvoorbeeld en { "type": "module" } drukt node main.js 28.27 af. Dezelfde bestanden werken via een browsermodulescript dat via HTTP wordt aangeboden.

Herken CommonJS en ingebouwde modules

CommonJS is het oudere modulesysteem van Node.js. Het gebruikt require() om synchroon te laden en module.exports om waarden aan te bieden. Een ES-module kan module.exports van een CommonJS-pakket als standaardimport importeren. Huidige Node.js-versies kunnen ook synchrone ES-modulegrafen laden met require; await op moduleniveau in zo'n graaf verhindert synchroon laden.

Gebruik in een ES-module import { readFile } from "node:fs/promises"; voor een ingebouwde Node.js-module. require, module en __dirname zijn CommonJS-variabelen, geen globale variabelen van ES-modules. import.meta.url geeft de URL van de module; recente Node.js-versies bieden ook import.meta.dirname voor lokale bestandsmodules.

Als een importinstructie wordt afgewezen omdat die buiten een module staat, controleer dan de instelling van de lader: type="module" in browser-HTML, of het pakkettype of de extensie in Node.js.

Belangrijkste punten

  • Een browserstartmodule gebruikt type="module" en wordt normaal uitgesteld.
  • Gebruik een lokale server en koppel eventhandlers vanuit de module.
  • Browsers hebben een importmap of buildtools nodig om pakketnamen zonder pad op te lossen.
  • Node.js gebruikt bestandsextensies en het veld type van het dichtstbijzijnde pakket.
  • CommonJS gebruikt require en module.exports; ES-modules gebruiken import en export.

2.3 Laad functionaliteit wanneer je die nodig hebt en scheid verantwoordelijkheden

Een statische import declareert een afhankelijkheid die nodig is bij het laden van een module. Dynamische import is een expressie: die begint te laden wanneer de uitvoering de expressie bereikt en geeft een promise terug. Gebruik dit voor functionaliteit die bij veel bezoeken niet nodig is.

Wacht op het naamruimteobject
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);
  }
});

Hier zijn measurements de gegevens die de pagina heeft verzameld. De eerste klik laadt de grafiekmodule en roept haar geëxporteerde functie aan. Latere klikken hergebruiken de uitgevoerde module. De promise kan worden afgewezen bij een fout tijdens het laden of uitvoeren, dus vangt de eventhandler die af.

import("./chart.js").drawChart probeert een eigenschap van de promise te lezen, niet van de geladen module. Wacht op de promise of gebruik .then. Gebruik voor een standaardexport de eigenschap default van de naamruimte: const { default: Chart } = await import("./chart.js");. Anders dan een statische declaratie kan deze expressie binnen een functie of voorwaarde voorkomen en kan het pad tijdens de uitvoering worden berekend.

Wacht tijdens de initialisatie van een module

Een ES-module kan await op moduleniveau buiten een functie gebruiken:

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

Modules die afhankelijk zijn van deze module wachten totdat de uitvoering ervan is voltooid voordat hun eigen lichamen worden uitgevoerd. Onafhankelijke modules kunnen verdergaan. Een traag configuratieverzoek vertraagt daardoor de afhankelijke modules, niet noodzakelijk elk deel van het programma. Klassieke scripts en CommonJS staan await op moduleniveau niet toe; gebruik deze modulefunctie voor initialisatie die afhankelijke modules echt eerst nodig hebben.

Geef elke module één duidelijke taak

Een takenapplicatie kan deze grenzen gebruiken:

ModuleVerantwoordelijkheid
todo.jsDe klasse Todo exporteren
storage.jsGegevens laden en opslaan via localStorage
ui.jsDe lijst op de pagina renderen
main.jsModules en eventhandlers verbinden

De gegevens- en opslagmodules importeren de gebruikersinterface niet. Je kunt ze testen en hergebruiken zonder pagina-elementen te maken. Als je berekeningen en opslag buiten eventhandlers houdt, zijn fouten ook gemakkelijker te vinden.

Privétoestand op het hoogste niveau wordt gedeeld tussen importeurs. In let nextId = 1; export function createId() { return nextId++; } blijft de variabele privé terwijl de functie gecontroleerde toegang biedt. Twee importeurs die de functie elk één keer aanroepen, krijgen 1 en 2, geen twee aparte tellers die bij 1 beginnen.

Beheers het werk tijdens het importeren

import "./setup.js"; is een import voor neveneffecten: die laadt en voert de module uit zonder lokale namen op te vragen. Neveneffecten kunnen nuttig zijn voor initialisatie, maar een herbruikbare module is gemakkelijker te testen wanneer die op het hoogste niveau functionaliteit definieert en haar functies het werk expliciet starten.

Een indexbestand of herexportverzamelbestand verzamelt herexports. Het kan een interface vereenvoudigen, maar grote herexportverzamelbestanden kunnen extra code binnenhalen en een cyclus verbergen. Een circulaire afhankelijkheid ontstaat wanneer modules rechtstreeks of via andere modules van elkaar afhankelijk zijn. Een cyclus kan werken, maar als je een binding leest voordat de exporterende module die initialiseert, ontstaat een ReferenceError. Verplaats gedeelde definities naar een derde module die beide kanten importeren om die afhankelijkheidscyclus te doorbreken.

Belangrijkste punten

  • import() geeft een promise voor een modulenaamruimte terug en kan binnen een functie worden uitgevoerd.
  • Wacht op dynamisch laden en handel afgewezen promises af.
  • Await op moduleniveau vertraagt de uitvoering van afhankelijke modules.
  • Scheid gegevens, opslag, renderen en het koppelen van events in modules met een duidelijke taak.
  • Eén uitgevoerde module kan privétoestand bevatten die door al haar importeurs wordt gedeeld.
  • Verplaats gedeelde definities naar een derde module om een circulaire afhankelijkheid te doorbreken.
3

Voer een project herhaalbaar uit met npm

Een project heeft een duidelijke beschrijving nodig van zijn opdrachten en de pakketten waarvan het afhankelijk is. npm bewaart die informatie in pakketbestanden en installeert de code die deze bestanden beschrijven. Leer scripts te lezen voordat je ze uitvoert, ontwikkeltools te onderscheiden van productafhankelijkheden en versiebereiken samen met een vergrendelingsbestand te gebruiken. Met deze keuzes kan een andere computer het project opnieuw opbouwen zonder een map met geïnstalleerde pakketten te kopiëren.

3.1 Beschrijf en voer een npm-project uit

npm is de pakketbeheerder die met Node.js wordt meegeleverd. De naam verwijst zowel naar een opdrachtregelprogramma als naar het openbare pakketregister. Een pakket is een map die wordt beschreven door package.json; de hoofdmap van een project is de map die dat bestand bevat.

Maak de projectbeschrijving

Voer node -v en npm -v uit om de geïnstalleerde hulpmiddelen te controleren. Ga naar de bedoelde projectmap voordat je npm init uitvoert. De interactieve opdracht stelt vragen; npm init -y accepteert de standaardwaarden. Bewerk daarna het bestand om het project te beschrijven.

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

Dit is JSON, geen JavaScript-objectliteral. Sleutels en strings gebruiken dubbele aanhalingstekens. Commentaar en afsluitende komma's zijn ongeldig. Een ontleedfout kan npm stoppen voordat het een opdracht uitvoert.

De name bestaat uit kleine letters en is geschikt voor een URL; namen van gepubliceerde pakketten hebben maximaal 214 tekens. version beschrijft dit project, niet de Node.js-versie ervan. private: true voorkomt onbedoelde publicatie via npm. Met type: "module" laat je Node.js de .js-bestanden van het pakket als ES-modules laden.

Gepubliceerde pakketten kunnen main en exports gebruiken om toegangspunten voor hun gebruikers te definiëren. Een optionele vermelding engines, zoals { "node": ">=22" }, geeft de ondersteunde Node.js-versies aan. Lees die vereisten wanneer een project op een oudere installatie mislukt.

Gebruik scripts als takenmenu

npm run toont de beschikbare scripts. In dit voorbeeld voert npm run lint eslint . uit, voert npm start de applicatie uit en voert npm test de testrunner uit. start en test hebben deze korte vormen; andere taaknamen gebruiken normaal npm run.

npm voegt de map node_modules/.bin van het project tijdelijk toe aan het zoekpad voor opdrachten. Een lokaal geïnstalleerd hulpmiddel kan daardoor rechtstreeks op naam in een script worden opgenomen. Iedereen die het project gebruikt, voert hetzelfde vastgelegde hulpmiddel uit in plaats van afhankelijk te zijn van een globale installatie.

Extra argumenten volgen na --: npm run lint -- --fix geeft --fix door aan ESLint. Het script geeft de taak een vaste naam, ook als het team het achterliggende hulpmiddel verandert. Begin bij het veld scripts wanneer je leert werken met een onbekend project.

Lees versienummers

Semantische versienummering gebruikt MAJOR.MINOR.PATCH. Vanaf 2.4.1 wordt een compatibele foutoplossing 2.4.2; een compatibele functie wordt 2.5.0; een ingrijpende wijziging wordt 3.0.0. Een overstap naar een nieuwe majorversie kan wijzigingen vereisen in code die het pakket gebruikt. Vóór 1.0.0 bevindt een project zich in een vroege ontwikkelfase en kunnen uitgaven vrijer veranderen.

Voer af en toe een pakketopdracht uit

npx serve voert de geïnstalleerde opdracht uit als die lokaal beschikbaar is. Anders kan npx vragen om het pakket tijdelijk te downloaden en uit te voeren. Dit is handig voor een hulpmiddel dat geen permanente projectafhankelijkheid hoeft te worden. Controleer de exacte pakketnaam en de betrouwbaarheid van de code voordat je die installeert of uitvoert: pakketopdrachten en installatiescripts kunnen met jouw rechten worden uitgevoerd.

Een opdracht in de verkeerde map kan mislukken doordat package.json ontbreekt, of een installatie kan pakketbestanden op een onbedoelde plek maken. Controleer eerst de huidige map. Houd scripts begrijpelijk en vermijd opdrachttrucs die specifiek zijn voor één besturingssysteem wanneer het project op meerdere systemen moet werken.

Belangrijkste punten

  • package.json beschrijft het project, de scripts en de afhankelijkheden met geldige JSON.
  • private: true voorkomt publicatie via npm; type stelt het Node.js-moduleformaat in.
  • Gebruik npm-scripts om lokaal geïnstalleerde hulpmiddelen consequent uit te voeren.
  • Semantische versies onderscheiden ingrijpende wijzigingen, compatibele functies en foutoplossingen.
  • npx kan een lokale opdracht uitvoeren of er tijdelijk een downloaden.

3.2 Installeer en werk de juiste pakketversies bij

Een afhankelijkheid is code waarop een project steunt. npm legt directe afhankelijkheden vast in package.json, installeert pakketten in node_modules en legt de exacte geïnstalleerde afhankelijkheidsboom vast in package-lock.json.

Scheid productcode van ontwikkeltools

npm install date-fns voegt een pakket voor de uitvoering toe aan dependencies. npm install --save-dev eslint voegt een ontwikkeltool toe aan devDependencies; -D is de korte vorm. Linters, codeopmakers, testrunners, bundlers en TypeScript horen normaal in de ontwikkellijst.

Wanneer een ander project een gepubliceerd pakket installeert, installeert npm de afhankelijkheden van dat pakket maar niet de ontwikkelafhankelijkheden. Een browserapplicatie kan uitvoeringsafhankelijkheden nog steeds in haar uiteindelijke bestanden bundelen, ook al is de buildtool zelf een devDependency.

npm install zonder pakketnaam installeert de afhankelijkheden die voor het project zijn vermeld. npm uninstall <package> verwijdert een pakket en de vermelding ervan. Na installatie van date-fns kunnen Node.js en buildtools import { format } from "date-fns"; oplossen. Een gewone browser heeft nog steeds een hulpmiddel nodig dat de naam oplost, zoals een importmap of ontwikkelserver.

Lees het toegestane bereik
VermeldingStabiele versies die zijn toegestaan
^4.17.21Minstens 4.17.21, lager dan 5.0.0
~4.17.21Minstens 4.17.21, lager dan 4.18.0
4.17.21Precies 4.17.21
^0.3.1Minstens 0.3.1, lager dan 0.4.0

De caret is de gebruikelijke standaard van npm. Voor versies vanaf 1.0.0 staat die compatibele minor- en patchupdates toe. Onder 1.0.0 is die strenger. Voor ^2.3.0 voldoen 2.3.5 en 2.9.0; 2.2.9 is te oud en 3.0.0 overschrijdt de majorgrens.

Een toegestaan bereik duidt niet één geïnstalleerde versie aan. Het vergrendelingsbestand doet dat wel, ook voor transitieve afhankelijkheden: de pakketten die de door jou gekozen pakketten nodig hebben.

Maak een installatie opnieuw

Deel package.json en package-lock.json met het project. Laat npm het vergrendelingsbestand onderhouden. De gegenereerde map node_modules kan opnieuw worden opgebouwd en is niet het bestand dat je moet delen.

Gebruik npm install tijdens de ontwikkeling wanneer vastgelegde afhankelijkheden mogen veranderen. Gebruik npm ci voor een schone, herhaalbare installatie: de opdracht vereist het vergrendelingsbestand, verwijdert een bestaande node_modules, installeert de vastgelegde boom en herschrijft geen van beide pakketbestanden. De opdracht mislukt als het pakketbestand en het vergrendelingsbestand niet overeenkomen. Herstel dat verschil bewust tijdens de ontwikkeling; het verwijderen van het vergrendelingsbestand kan ongemerkt veel versies veranderen.

Werk bij met een reden

npm outdated vergelijkt de huidige, toegestane en nieuwste versies. De toegestane versie is de nieuwste versie die binnen het gedeclareerde bereik valt; de nieuwste versie kan een majorversie daarbuiten zijn. npm update werkt bij binnen de bereiken en legt de resulterende boom vast. Om bewust een majorgrens over te steken, lees je de wijzigingsgeschiedenis, voer je npm install <package>@latest uit en controleer je het project met de tests.

Installeer projecthulpmiddelen lokaal zodat hun versies worden vastgelegd. Controleer voordat je een afhankelijkheid toevoegt het onderhoud, het gebruik, de licentie en of een ingebouwde functie het probleem al oplost. structuredClone() voorziet in de ondersteunde behoeften aan diepe kopieën; Intl.DateTimeFormat maakt datums op zonder datumpakket.

npm audit meldt bekende kwetsbaarheden in geïnstalleerde versies. Lees het rapport om de betreffende code en het gebruik ervan te begrijpen. npm audit fix kan compatibele oplossingen toepassen, maar bewijst niet dat elke kwetsbaarheid is opgelost of dat een update het gedrag van het project behoudt.

Belangrijkste punten

  • Gebruik dependencies voor uitvoeringscode en devDependencies voor ontwikkel- en buildtools.
  • Versiebereiken staan uitgaven toe; het vergrendelingsbestand legt exacte geïnstalleerde versies vast.
  • Deel beide pakketbestanden en bouw node_modules opnieuw op.
  • npm ci installeert op basis van het vergrendelingsbestand zonder het te wijzigen en wijst niet-overeenkomende pakketbestanden af.
  • npm update blijft binnen gedeclareerde bereiken; overstappen naar een nieuwe majorversie vereist een bewuste keuze.
  • Lees beveiligingsrapporten en controleer het gedrag na updates van afhankelijkheden.
4

Controleer code en maak een build met ontwikkelaarstools

Verschillende hulpmiddelen beantwoorden verschillende vragen over een project. Een linter zoekt naar verdachte code, een codeopmaker maakt die op, tests controleren het gedrag en een build bereidt browserbestanden voor op een uitgave. Een ontwikkelserver houdt de bewerkingscyclus snel. Leer wat elk resultaat je vertelt en wat het niet controleert, zodat je een geslaagde opmaakopdracht of ontwikkelpagina niet aanziet voor bewijs dat de hele applicatie werkt.

4.1 Vind codeproblemen en maak code consistent op

Een linter leest broncode zonder die uit te voeren en meldt waarschijnlijke fouten of riskante patronen. Een codeopmaker herschrijft de opmaak op een consistente manier. ESLint en Prettier werken vaak samen omdat die taken verschillende problemen oplossen.

Configureer de controles

npm init @eslint/config@latest stelt vragen over het project, installeert ontwikkelpakketten en maakt een configuratiebestand. Huidige ESLint-versies gebruiken vlakke configuratie, meestal in 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",
    },
  },
];

De aanbevolen configuratie schakelt regels in die fouten opsporen. De globale browsernamen vertellen ESLint dat namen zoals document bestaan. Zo wordt een bestaande functie van de omgeving niet als een ongedefinieerde naam behandeld.

Meldingsniveaus van regels zijn "off", "warn" en "error", ook geschreven als 0, 1 en 2. Fouten veroorzaken een afsluitcode voor mislukking; alleen waarschuwingen laten de opdracht standaard niet mislukken. Een waarschuwing blijft informatie die je moet lezen, ook als het script succesvol eindigt.

Lees een lintrapport
function total(items) {
  let sum = 0;
  let unused = 5;
  for (const item of items) {
    if (item.quantity == "2") sum += item.price;
  }
  return summ;
}

Onder de bovenstaande configuratie levert dit vijf meldingen op. total wordt nooit gebruikt. sum wordt bijgewerkt, maar de waarde wordt buiten die bijwerkingen nooit gebruikt. unused wordt niet gebruikt. De regel eqeqeq markeert == en no-undef vindt de verkeerd gespelde naam summ. Een aanroep van deze functie zou bij die ongedefinieerde naam mislukken, maar de linter kan de fout zonder aanroep vinden.

Begin bij de regelnaam en locatie in het rapport. Corrigeer het bedoelde gedrag en voer de opdracht opnieuw uit. npm run lint -- --fix vraagt om veilige automatische oplossingen wanneer het project een script lint heeft. De opdracht kan niet voor elke waarschuwing de juiste bedrijfslogica bepalen. Schakel een regel alleen voor één regel code uit wanneer daar een reden voor is en leg die reden naast het commentaar vast.

Laat één codeopmaker de opmaak verzorgen
npm install --save-dev --save-exact prettier
npx prettier . --write
npx prettier . --check

--write wijzigt bestanden; --check meldt verschillen in opmaak zonder de bestanden te wijzigen. Met de standaardinstellingen wordt const point={x:1,y:2} omgezet in const point = { x: 1, y: 2 };. Opties zoals "singleQuote": true komen in .prettierrc.

HulpmiddelHoofdvraag
ESLintBevat deze code een patroon dat een regel markeert?
PrettierHeeft de code de gekozen opmaak?
TestrunnerLevert de code het verwachte gedrag op?

De aanbevolen regels van ESLint schrijven de opmaak van Prettier niet voor, zodat die configuratie opmaakconflicten voorkomt. Als een andere ESLint-configuratie conflicterende stijlregels toevoegt, schakelt eslint-config-prettier die regels uit. Als je twee concurrerende codeopmakers uitvoert, kunnen bestanden steeds heen en weer veranderen.

Voeg scripts lint en format toe zodat controles gemakkelijk te herhalen zijn. Editorextensies kunnen na configuratie tijdens het typen meldingen tonen en bij het opslaan opmaken. Beide hulpmiddelen slaan node_modules standaard over; voeg gegenereerde uitvoer zoals dist toe aan de juiste negeerinstellingen. Een functie zonder lintmeldingen kan nog steeds de omtrek berekenen terwijl die de oppervlakte moet berekenen; gedrag heeft tests nodig.

Belangrijkste punten

  • Een linter vindt geconfigureerde problemen in broncode zonder het programma uit te voeren.
  • Het foutniveau van ESLint laat de opdracht mislukken; waarschuwingen doen dat standaard niet.
  • Prettier wijzigt de opmaak met --write en controleert die met --check.
  • Gebruik compatibele lint- en opmaakregels en tests voor gedrag.

4.2 Ontwikkel lokaal en bouw browserbestanden

Een browser kan enkele ES-modules rechtstreeks laden, maar grotere projecten gebruiken ook geïnstalleerde pakketten en bestanden die transformatie nodig hebben. Een ontwikkelserver bereidt bestanden voor terwijl je bewerkt. Een bundler volgt afhankelijkheden om bestanden te maken die geschikt zijn voor uitgave.

Doorloop de Vite-cyclus
npm create vite@latest shape-lab
cd shape-lab
npm install
npm run dev
npm run build
npm run preview

Kies voor dit project het JavaScript-sjabloon Vanilla. De generator levert ontwikkel- en buildscripts. npm run dev toont een lokaal adres, vaak http://localhost:5173. Open dat adres tijdens het bewerken. In Vite is index.html het toegangspunt en laadt dit bestand doorgaans /src/main.js met een modulescript.

De ontwikkelserver lost pakketnamen op en transformeert bestanden waar nodig. Als je een bestand opslaat, wordt een update gestart. Modulevervanging tijdens uitvoering, of HMR, vervangt een gewijzigde module in de actieve pagina; bij ondersteunde updates kan de toestand behouden blijven zonder een volledige herlaadactie af te dwingen.

npm run build schrijft geoptimaliseerde uitvoer naar dist. npm run preview maakt die uitvoer lokaal beschikbaar zodat je de daadwerkelijke productiebuild kunt controleren. Voor de voorbeeldweergave is een bestaande build nodig; er wordt geen nieuwe gemaakt. Bewerk bronbestanden, want een volgende build vervangt de gegenereerde uitvoer.

Begrijp de wijzigingen voor productie
BuildfunctieDoel
BundelenModules combineren tot minder browserbestanden
Verwijdering van ongebruikte codeCode verwijderen waarvan de build kan aantonen dat die ongebruikt is
MinificatieDe omvang verkleinen door opmaak te verwijderen en namen in te korten
InhoudshashesBestandsnamen wijzigen wanneer de inhoud verandert, ter ondersteuning van caching
CodeopsplitsingEen deel van de code in aparte stukken bewaren die later kunnen worden geladen

Een hulpmodule kan bijvoorbeeld zowel formatArea als formatVolume exporteren. Als alleen formatArea wordt gebruikt en het veilig is om de andere code te verwijderen, kan de verwijdering van ongebruikte code formatVolume weglaten. Statische imports en exports maken afhankelijkheden zichtbaar. Neveneffecten op het hoogste niveau van een module moeten mogelijk blijven bestaan, ook als geen van de exports wordt gebruikt.

Een dynamische import() geeft de buildtool een grens aan voor later laden. Buildtools kunnen hiervoor aparte stukken maken; de indeling hangt af van de build, dus wordt een bronmodule niet altijd precies één uitvoerbestand.

Een naam zoals assets/index-4f2a9c1b.js verandert met de inhoud, zodat browsers bestanden lang kunnen cachen zonder na een update een oud bestand aan te bieden. Een sourcemap verbindt gegenereerde locaties met de oorspronkelijke bronregels, wat aanroepsporen en debuggen gemakkelijker maakt wanneer sourcemaps beschikbaar zijn.

Neem assets en openbare configuratie op

Vite verwerkt ook assets: import "./style.css"; neemt stijlen op en import logoUrl from "./logo.png"; levert de uiteindelijke URL van de afbeelding. De build kan die verwijzingen bijwerken zodat ze overeenkomen met gegenereerde bestandsnamen.

Lees modusinformatie via import.meta.env.MODE. De standaardwaarden zijn "development" voor ontwikkeling en "production" voor een build; een eigen modus kan een andere naam gebruiken. Eigen omgevingswaarden die met VITE_ beginnen, worden standaard beschikbaar gemaakt aan browsercode. Alles wat naar de browser wordt verstuurd, is openbaar: bewaar geheime sleutels en wachtwoorden op een server, buiten browsercode en beschikbaar gemaakte omgevingsvariabelen.

Controleer niet alleen de ontwikkelpagina. Maak vóór een uitgave een build en bekijk die om problemen in getransformeerde uitvoer en assetpaden te vinden. dist/index.html rechtstreeks vanaf schijf openen geeft niet dezelfde situatie als de site via HTTP aanbieden. Een kleine pagina met enkele gewone modules heeft mogelijk alleen een statische server nodig, zonder volledige buildtool.

Belangrijkste punten

  • Een ontwikkelserver lost bestanden op en transformeert ze tijdens het bewerken; een productiebuild maakt uitvoer voor een uitgave.
  • HMR kan gewijzigde code vervangen terwijl ondersteunde paginatoestand behouden blijft.
  • Verwijdering van ongebruikte code verwijdert code alleen wanneer de build die veilig kan weglaten.
  • Inhoudshashes ondersteunen caching en sourcemaps verbinden uitvoer met de broncode.
  • Maak eerst een build en bekijk daarna de gegenereerde uitvoer lokaal.
  • Browserbundels en beschikbaar gemaakte omgevingswaarden zijn openbaar.

4.3 Test gedrag met asserties

Een geautomatiseerde test voert code uit met bekende invoer en controleert het resultaat met asserties. Een unittest richt zich op een klein onderdeel, zoals een functie of methode. De testrunner vindt tests, voert ze uit, meldt fouten en eindigt zonder succes wanneer een test mislukt.

Voorbereiden, uitvoeren, controleren

Bereid de invoer voor, roep de code aan en controleer het verwachte resultaat. Een bruikbare testnaam beschrijft gedrag. Voor een rechthoekklasse waarvan de constructor een negatieve zijde afwijst:

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);
});

De eerste assertie controleert 12 cm², een onafhankelijk bekend resultaat. De tweede geeft een functie door aan assert.throws, zodat de assertie de fout kan waarnemen. Als je node --test uitvoert, worden bestanden met namen zoals rectangle.test.js gevonden; een pakketscript "test": "node --test" maakt npm test mogelijk.

De strikte assertiemodus gebruikt Object.is voor assert.equal zonder impliciete typeconversie. assert.deepEqual vergelijkt de inhoud van objecten en arrays. Verschillende arrays met dezelfde waarden zijn niet hetzelfde object, dus is een strikte identiteitsvergelijking niet de juiste controle voor gelijke inhoud.

Gebruik dezelfde principes in 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 gebruikt describe om te groeperen en it voor afzonderlijke tests. Voer npx vitest uit om op wijzigingen te letten, of npx vitest run voor één uitvoering. Jest biedt een vergelijkbare stijl. Gebruik toEqual voor inhoud en toBe voor identiteit of primitieve waarden.

Neem grenzen en numerieke beperkingen mee

Test de exacte eindpunten van een toegestaan bereik en invoer die daar net buiten valt. Een thermostaat die 10 tot en met 30 °C accepteert, heeft tests nodig die 10 en 30 accepteren en tests die 9,5 en 30,5 afwijzen. Voeg aparte controles toe voor niet-numerieke en niet-eindige waarden als de interface die afwijst. Tests mogen niet afhangen van een object dat door een eerdere test is gewijzigd of van de uitvoeringsvolgorde.

Rekenen met drijvendekommagetallen komt mogelijk niet exact overeen met een geschreven decimaal getal: 0.1 + 0.2 is 0.30000000000000004. Gebruik voor een geschikte tolerantie assert.ok(Math.abs(actual - expected) < 1e-9). Een cirkel met straal 3 heeft een oppervlakte van ongeveer 28,274333882 cm²; Vitests toBeCloseTo(28.27, 2) controleert of de waarde bij die decimale precisie dichtbij genoeg ligt. Kies een tolerantie die past bij wat de test moet vaststellen.

Leer van een mislukte test

Lees het genoemde gedrag, de verwachte en werkelijke waarden en de locatie in de broncode. Bepaal of de implementatie of de verwachting van de test fout is. Bij testgestuurde ontwikkeling schrijf je een test die mislukt, implementeer je genoeg om die te laten slagen en verbeter je daarna de code terwijl de tests blijven slagen.

Exporteer logica uit modules en geef invoer door als argumenten. Een eventhandler kan dan paginagegevens verzamelen en die logica aanroepen, in plaats van berekeningen met DOM-werk te vermengen. Code die afhankelijk is van het DOM kan een gesimuleerde browser zoals jsdom gebruiken. Wacht in een asynchrone test op asynchroon werk, zodat de test niet kan eindigen voordat de controles zijn uitgevoerd. Een test die alleen de formule van de implementatie herhaalt, kan ook de fout daarin herhalen; gebruik verwacht gedrag en onafhankelijke voorbeelden.

Belangrijkste punten

  • Tests voeren code uit en gebruiken asserties om onafhankelijk verwacht gedrag te controleren.
  • Bereid invoer voor, voer de code uit en controleer één gedraging met een bruikbare testnaam.
  • Vergelijk de inhoud van verschillende arrays of objecten met gelijke inhoud.
  • Test grenzen en ongeldige invoer en gebruik geschikte toleranties voor drijvendekommagetallen.
  • Wacht op asynchroon werk en houd tests onafhankelijk van de uitvoeringsvolgorde.
5

Plaats typen en frameworks in de werkwijze

TypeScript en front-endframeworks bouwen voort op de al geïntroduceerde JavaScript-hulpmiddelen. Typen helpen een editor en typecontrole om vóór de uitvoering waarden te vinden die niet bij elkaar passen. Componenten helpen interfaces te organiseren die gegevens delen en wijzigen. Beide nemen de noodzaak niet weg om modules, afhankelijkheden of tests te begrijpen. Gebruik de projectscripts als overzicht van hoe deze onderdelen samenwerken en voeg hulpmiddelen toe wanneer het werk ze een duidelijk doel geeft.

5.1 Begrijp wat TypeScript controleert

TypeScript voegt statische typesyntaxis toe aan JavaScript. Een type beschrijft wat voor soort waarde code verwacht. De typecontrole gebruikt die beschrijvingen voordat het programma wordt uitgevoerd, zodat fouten aan het licht kunnen komen voordat een gebruiker ermee te maken krijgt.

Controleer een aanroep vóór de uitvoering
function area(width: number, height: number): number {
  return width * height;
}
area(3, "4"); // type error: the second argument is a string

Beide parameters moeten getallen zijn. De geschreven waarde "4" is een string, dus meldt de typecontrole dat de typen niet overeenkomen. Gewoon JavaScript zou die string bij de vermenigvuldiging impliciet converteren: 3 * "4" geeft 12. Bij optellen geeft 3 + "4" de string "34". Een typefout duidt aan dat de bedoelde invoer niet overeenkomt, ook wanneer JavaScript de expressie zou kunnen uitvoeren.

Een interface beschrijft de structuur van een object:

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

Een klasse die met implements Shape is gedeclareerd, moet de opgegeven eigenschappen en methoden met compatibele typen aanbieden. De typecontrole kan ook verkeerd gespelde eigenschappen, een onjuist aantal argumenten en mogelijke undefined-waarden opsporen wanneer strikte controle is ingeschakeld.

Scheid controleren van het verwijderen van typen
Hulpmiddel of handelingWat het doet
tscControleert typen en genereert normaal JavaScript
tsc --noEmitControleert typen zonder uitvoer te schrijven
TypeScript-transformatie van ViteVerwijdert typesyntaxis voor de uitvoering
Typesyntaxis verwijderen in Node.jsVoert ondersteunde TypeScript-code met verwijderbare typesyntaxis uit nadat de typen zijn verwijderd

TypeScript-projectinstellingen staan in tsconfig.json. Een Vite-build stelt op zichzelf niet vast dat alle typen correct zijn. Projecten voeren tsc --noEmit meestal afzonderlijk uit. Huidige Node.js-versies kunnen ondersteunde .ts-bestanden rechtstreeks uitvoeren, maar ook bij het verwijderen van typesyntaxis worden de typen niet gecontroleerd.

Behoud controles tijdens de uitvoering aan gegevensgrenzen

Typeannotaties worden vóór de uitvoering verwijderd. Het verwachte type declareren van gegevens uit fetch() of JSON.parse() controleert de werkelijke waarde niet. Controleer externe gegevens in de draaiende code voordat je erop vertrouwt. Een server kan een string sturen ook als een typedeclaratie zegt dat een veld numeriek is.

TypeScripts private en readonly zijn beperkingen van de typecontrole; ze bieden niet de afscherming die JavaScripts # tijdens de uitvoering biedt. Privévelden van JavaScript blijven afgedwongen wanneer het programma draait. TypeScript laat een programma ook niet sneller draaien en bewijst niet dat berekeningen correct zijn.

Het type any schakelt nuttige controles voor een waarde uit. Het kan een foutmelding onderdrukken terwijl de oorspronkelijke fout blijft bestaan. Een onjuiste aanname corrigeren of een echte gegevenscontrole toevoegen geeft de typecontrole betere informatie.

Voer TypeScript in beheersbare stappen in

Een JavaScript-bestand kan beginnen met // @ts-check en JSDoc gebruiken zoals /** @param {number} width */ om controles te krijgen in editors die dit ondersteunen, zonder een .ts-bestand te worden. Een project kan later bestanden één voor één hernoemen. Bibliotheken kunnen typedefinities in .d.ts-bestanden leveren; definities van de gemeenschap worden vaak verspreid onder @types/....

Grotere, lang bestaande projecten krijgen duidelijkere interfaces, veiliger herstructurering en betere automatische aanvulling in de editor. Voor een klein script zijn een extra buildstap en nieuwe syntaxis misschien nog niet de moeite waard. Tests blijven in beide gevallen nuttig: een oppervlaktefunctie met correcte typen kan nog steeds een verkeerde numerieke berekening teruggeven.

Belangrijkste punten

  • TypeScript controleert verwachte waardetypen vóór de uitvoering.
  • Typesyntaxis verwijderen staat los van typen controleren.
  • Typedeclaraties valideren externe gegevens niet terwijl het programma draait.
  • JavaScript dwingt afscherming met # tijdens de uitvoering af; TypeScript controleert private statisch.
  • Controle met JSDoc maakt geleidelijke invoering mogelijk voordat je bestanden naar TypeScript converteert.

5.2 Combineer hulpmiddelen rond de behoeften van het project

Een bibliotheek levert code die je programma aanroept. Een framework biedt een applicatiestructuur en roept je code op de juiste momenten aan. Deze verandering in de aansturing helpt grotere interfaces te coördineren, maar steunt nog steeds op JavaScript, modules en een gereedschapsketen voor het project.

Deel een interface in componenten in

React, Vue, Svelte en Angular organiseren gebruikersinterfaces met componenten: herbruikbare onderdelen zoals een navigatiebalk of een taak. Een component combineert opmaak en gedrag, vaak met stijlen. Wanneer de toestand van een component verandert, coördineert het gebruikersinterfacesysteem de relevante updates van de pagina.

Metaframeworks zoals Next.js, Nuxt, SvelteKit en Astro voegen een uitgebreidere inrichting toe, waaronder routering, renderen op de server en buildondersteuning. Hun precieze functies verschillen. Kennis van JavaScript-functies, events, asynchrone code en modulegrenzen helpt bij het leren van elk van deze frameworks.

Een pagina met enkele onafhankelijke interactieve functies kan met gewoon JavaScript overzichtelijk zijn. Een framework wordt nuttig wanneer veel weergaven veranderende gegevens moeten delen. Kies het voor die behoefte in plaats van aan te nemen dat elke pagina de grootste gereedschapsketen vereist.

Volg hoe de hulpmiddelen samenwerken

Frameworkpakketten worden via npm geïnstalleerd en als modules geïmporteerd. Buildtools transformeren syntaxis zoals JSX of frameworkspecifieke bestanden. TypeScript kan interfaces tussen onderdelen controleren. Linten, opmaken en testen behouden hun eigen taken, ongeacht de keuze voor de gebruikersinterface.

Begin een eenvoudig project en voeg de hulpmiddelen toe die het team gebruikt:

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

Een Vite-sjabloon levert ontwikkel- en buildtools. Extra pakketten installeren configureert ze niet: voeg de ESLint-configuratie toe, maak tests en stel editorextensies in om bij het opslaan te linten en op te maken. Een scriptsveld kan deze taken aanbieden:

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

Deze vermeldingen horen binnen "scripts" in package.json. Voer tijdens het bewerken npm run dev uit; de editor kan linten en opmaken wanneer bestanden veranderen. Voer npm test uit voordat je werk deelt. Voer vóór een uitgave npm run build en npm run preview uit. De gebouwde map dist van een statische site kan daarna naar een geschikte statische host worden geüpload.

Zoek het bestand dat een taak bepaalt
Bestand of mapRol
package.jsonOpdrachten en bereiken van directe afhankelijkheden
package-lock.jsonExacte afhankelijkheidsboom
node_modules/Gegenereerde geïnstalleerde pakketten
eslint.config.jsLintregels en omgevingen
.prettierrcOpmaakopties
vite.config.jsOntwikkel- en buildopties
tsconfig.jsonInstellingen voor TypeScript-controle en compilatie
dist/Gegenereerde builduitvoer

Begin bij een onbekend project met package.json: de scripts laten zien hoe het project wordt uitgevoerd en de afhankelijkheidslijsten tonen welke hulpmiddelen die scripts nodig hebben. Gegenereerde mappen kunnen opnieuw worden gemaakt; instellingen en broncode verklaren hoe je dat doet.

Leer nieuwe hulpmiddelen één voor één, zodat een fout nog een herkenbare oorzaak heeft. Gebruik de officiële documentatie voor de geïnstalleerde versie wanneer opdrachten of standaardinstellingen verschillen, omdat uitgaven van hulpmiddelen en frameworks vaker veranderen dan de basissyntaxis van JavaScript.

Belangrijkste punten

  • Je code roept een bibliotheek aan; een framework roept je code binnen zijn structuur aan.
  • Componenten coördineren herbruikbare delen van de gebruikersinterface en veranderende toestand.
  • Frameworkprojecten zijn nog steeds afhankelijk van modules, pakketten, builds en controles.
  • Sjablonen en pakketinstallatie configureren niet elk extra hulpmiddel automatisch.
  • Lees eerst pakketscripts om de werkwijze van een project te leren kennen.
  • Voeg hulpmiddelen toe om een concrete behoefte te vervullen en controleer de documentatie voor de geïnstalleerde versie.

Klassen en modules in JavaScript: voorbeelden

5 Walkthroughs

1

Bouw een kleine familie van objecten

18 stappen
Maak instanties, bewaak hun toestand, specialiseer gedrag en volg de gedeelde methoden die het model laten werken.
  1. 1
    IntroductieBegin met objecten die gedrag nodig hebben

    Een programma kan veel rechthoeken opslaan, maar elke rechthoek heeft ook bewerkingen nodig zoals oppervlakte en omtrek. Met een klasse kunnen die objecten de bewerkingen delen terwijl ze hun afmetingen apart houden.

    Volg het object vanaf het maken tot een methodeaanroep. Voeg daarna bewaakte toestand toe, onderscheid waarden op klasseniveau en specialiseer gedrag met overerving. Bekijk tot slot de prototypeketen om te zien waar de gedeelde methoden staan.

  2. 2
    VoorbeeldInitialiseer één instantie

    De constructor slaat waarden op in het nieuwe object. Hier zijn de afmetingen in centimeters:

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

    new maakt a en voert de constructor uit terwijl this daarnaar verwijst. De twee toewijzingen geven a een eigen breedte en hoogte.

  3. 3
    VoorbeeldRoep gedeeld gedrag aan met aparte gegevens

    Voeg const b = new Rectangle(5, 2); toe. Beide objecten kunnen area aanroepen, maar elke aanroep leest de afmetingen van het ontvangende object.

    a.area() vermenigvuldigt 3 met 4 en geeft 12 cm² terug. b.area() vermenigvuldigt 5 met 2 en geeft 10 cm² terug. De toewijzing b.width = 8 verandert alleen b, zodat de volgende oppervlakte 16 cm² is terwijl die van a 12 cm² blijft.

    De methode heeft niet voor elke rechthoek een aparte kopie van haar code nodig. De gegevens die de methode leest, komen uit this.

  4. 4
    TipBehoud het object in een callback

    Een methode van een object loshalen verbindt het ontvangende object er niet blijvend aan:

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

    Klassenmethoden worden in strikte modus uitgevoerd. De losgekoppelde aanroep heeft geen object vóór de punt, dus mislukt het lezen van this.width. De omhullende pijlfunctie houdt de oorspronkelijke methodeaanroep intact. a.area.bind(a) is een andere manier om een callback te maken die aan a is gebonden.

  5. 5
    UitdagingVoorspel een tweede aanroep

    Een nieuwe Rectangle(6, 2) wordt toegewezen aan tile. De instructie tile.width = 7 wordt uitgevoerd. Wat geeft tile.area() terug en waarom verandert dit niet een andere rechthoek die eerder is gemaakt?

    ---reveal---

    De methode geeft 14 cm² terug: zij leest de huidige breedte van het ontvangende object, 7 cm, en de hoogte, 2 cm. Elke instantie slaat haar eigen afmetingen op, dus wijzigt een verandering van tile.width geen andere instantie. Een methode delen maakt de instantievelden niet gedeeld.

  6. 6
    UitlegSla toestand op achter een setter

    Een thermostaat kan target beschikbaar maken terwijl #target privé wordt opgeslagen. Een getter leest de privéwaarde; een setter controleert een gevraagde wijziging.

    De setter wijst niet-eindige of niet-numerieke invoer en waarden buiten 10 tot en met 30 °C af voordat this.#target = value wordt toegewezen. Die volgorde is belangrijk: een fout opwerpen vóór de toewijzing behoudt de laatste geldige doelwaarde. De aparte opslagnaam voorkomt ook dat een setter zichzelf herhaaldelijk aanroept.

  7. 7
    VoorbeeldVolg een geaccepteerde en een afgewezen wijziging

    Begin met een doelwaarde van 20 °C voor de thermostaat. De toewijzing van 22 komt door beide controles, dus slaat de setter 22 op. De toewijzing van 35 werpt daarna een RangeError op; de opgeslagen waarde blijft 22.

    Number.isFinite(value) wijst ook "22", NaN en oneindigheid af. Alleen de bereikvergelijkingen zouden niet elk ongeldig type of elke ongeldige waarde afwijzen. Privéopslag beheerst directe toegang, terwijl validatie bepaalt wat de publieke interface accepteert.

  8. 8
    KernpuntKies opslag op klasse- of instantieniveau

    Een veld dat met static is gedeclareerd, hoort bij de klasse. Lees de ondergrens van de thermostaat als Thermostat.MIN, terwijl t.target de toestand van één instantie leest.

    Een statische teller kan bijhouden hoeveel objecten zijn gemaakt. Een gewoon veld begint daarentegen voor elk nieuw object afzonderlijk. Binnen een statische methode is this de klasse die de aanroep ontvangt, dus geeft die niet de doelwaarde of afmetingen van één instantie.

  9. 9
    UitdagingGebruik de publieke toegang

    Een subklasse van Thermostat moet haar doelwaarde verhogen van 20 naar 24 °C. De ouderklasse declareert #target en een publieke setter target die valideert. Hoe moet de subklasse de wijziging aanvragen en wat gebeurt er bij directe toegang met this.#target?

    ---reveal---

    Wijs this.target = 24 toe zodat de overgeërfde setter de waarde valideert en opslaat. De subklasse kan het privéveld van de ouderklasse niet rechtstreeks benoemen; dat gebruik van #target is een syntaxisfout. Overgeërfde getters en setters worden nog steeds uitgevoerd in de klasse die de privétoestand heeft gedeclareerd.

  10. 10
    VoorbeeldGeef verwante klassen een ouderklasse

    Een constructor van Shape slaat een naam op en de methode describe() roept this.area() aan. Een cirkel specialiseert de berekening:

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

    super initialiseert het deel van de ouderklasse voordat this.radius wordt gebruikt. Een cirkel is een vorm, dus past de overgeërfde beschrijving bij die rol.

  11. 11
    VoorbeeldLaat het ontvangende object de berekening kiezen

    Bij een straal van 2 cm geeft new Circle(2).describe() de tekst "Circle with area 12.57 cm²" terug. De beschrijvingsmethode is overgeërfd, maar haar aanroep this.area() vindt de overschreven methode van de cirkel.

    Een rechthoek kan diezelfde beschrijving overerven en vermenigvuldiging als eigen oppervlaktemethode aanbieden. Een lus die describe() op beide objecten aanroept, heeft geen aparte takken voor cirkel en rechthoek nodig. Deze gedeelde interface met verschillend gedrag is polymorfisme.

  12. 12
    UitlegBreid een methode van de ouderklasse uit

    Een vierkant kan super(side, side) in zijn constructor aanroepen om de rechthoek als ouderklasse gelijke afmetingen te geven. Een overschreven beschrijving kan vervolgens super.describe() aanroepen en de lengte van de zijde toevoegen.

    super(...) in de constructor en super.describe() in een methode hebben verschillende taken: de ene initialiseert de ouderklasse, de andere roept een methode van de ouderklasse aan. Een subklasse zonder eigen constructor geeft argumenten automatisch door.

  13. 13
    UitdagingKies een bruikbaar model

    Een object Report moet berichten versturen via een Notifier. Rapporten zijn geen meldingssystemen. Hoe moeten de objecten met elkaar worden verbonden en hoe vraagt het rapport om een melding?

    ---reveal---

    Gebruik compositie: geef het rapport een eigenschap voor het meldingssysteem en roep daarna een methode aan zoals this.notifier.send(message). Dit is een “heeft een”-relatie. Als het rapport Notifier zou uitbreiden om code te hergebruiken, zou dat betekenen dat elk rapport zelf een meldingssysteem is. Dat past niet bij het model.

  14. 14
    UitlegVind een methode via de keten

    De eigen eigenschappen van een cirkel bevatten gegevens zoals de straal. Wanneer de cirkel geen eigen describe heeft, zoekt JavaScript in Circle.prototype en daarna in Shape.prototype, waar die methode is opgeslagen.

    De gewone keten loopt via Object.prototype verder naar null. Als geen object in de keten een gevraagde eigenschap heeft, geeft het lezen ervan undefined. instanceof Shape slaagt normaal omdat Shape.prototype in de keten van de instantie voorkomt.

  15. 15
    VoorbeeldOverschaduw een overgeërfde instelling

    Maak settings met Object.create(defaults), waarbij defaults.fontSize gelijk is aan 16. Wijs settings.fontSize = 18 toe.

    De toewijzing maakt een eigen gegevenseigenschap die de overgeërfde eigenschap overschaduwt. De standaardwaarde blijft 16. Als je settings.fontSize verwijdert, verdwijnt de overschaduwing, zodat de volgende leesactie weer 16 op het prototype vindt. Dit verloop gaat uit van een gewone gegevenseigenschap; een overgeërfde setter kan een toewijzing in plaats daarvan afhandelen.

  16. 16
    UitdagingControleer eigendom afzonderlijk van toegang

    Een object panel erft theme: "light" over van een gewoon prototype en heeft geen eigen theme. Wat leveren panel.theme, Object.hasOwn(panel, "theme") en "theme" in panel op?

    ---reveal---

    Ze leveren "light", false en true op. Lezen en in kunnen overgeërfde eigenschappen vinden, terwijl Object.hasOwn alleen vraagt of de eigenschap op panel zelf is opgeslagen. Een geslaagde leesactie toont niet aan dat de eigenschap eigen is. Object.keys(panel) laat deze overgeërfde sleutel ook weg.

  17. 17
    UitdagingVerbind overerving, afscherming en opzoeken

    Sensor declareert #value, een publieke getter value en een methode describe() die this.value leest. IndoorSensor extends Sensor voegt geen leden toe. Waarom kan een binnensensor describe() aanroepen hoewel het lichaam van de klasse #value niet kan benoemen?

    ---reveal---

    Bij het opzoeken wordt de overgeërfde methode gevonden, die wordt uitgevoerd met de binnensensor als this. De getter die in Sensor is gedeclareerd, kan zijn eigen privéveld op die instantie lezen. Overerving levert het publieke gedrag zonder de subklasse directe toegang te geven tot de privénaam van de ouderklasse.

  18. 18
    SamenvattingBekijk een object in een bruikbare volgorde

    Vraag je bij het volgen van een klasse-instantie af waar haar gegevens zijn opgeslagen, welk object de methodeaanroep ontvangt en waar de methode bij het opzoeken wordt gevonden. Als een wijziging via een setter verloopt, volg dan de validatie vóór de toewijzing.

    Bekijk bij een onbekende hiërarchie extends en de constructorargumenten voordat je overschreven methoden volgt. Gebruik eigendomscontroles wanneer je opgeslagen sleutels nodig hebt en volg prototypes wanneer je overgeërfd gedrag wilt verklaren.

2

Verbind een programma over modulegrenzen heen

13 stappen
Exporteer een klasse, laad die in beide omgevingen en stel optioneel werk uit met behoud van duidelijke afhankelijkheden.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieVolg één afhankelijkheidsgraaf
  2. 2
    VoorbeeldExporteer de berekening
  3. 3
    VoorbeeldExporteer en gebruik de klasse
  4. 4
    UitdagingLees een gewijzigde export
  5. 5
    VoorbeeldStart de bestanden in een browser
  6. 6
    UitlegLos een pakketnaam op
  7. 7
    UitdagingKies de Node.js-lader
  8. 8
    VoorbeeldStel een optionele grafiek uit
  9. 9
    KernpuntBepaal wat op de initialisatie wacht
  10. 10
    UitdagingDoorbreek een onnodige cyclus
  11. 11
    TipHoud werk buiten imports
  12. 12
    UitdagingCombineer laden met een duidelijke interface
  13. 13
    SamenvattingVolg een modulefout per fase
3

Maak een npm-project opnieuw op een andere computer

11 stappen
Lees scripts, kies afhankelijkheidstypen en gebruik bereiken met een vergrendelingsbestand om de installatie te reproduceren.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieMaak het project reproduceerbaar
  2. 2
    VoorbeeldMaak de pakketbeschrijving
  3. 3
    VoorbeeldLees de taak voordat je die uitvoert
  4. 4
    UitdagingBepaal een versiewijziging
  5. 5
    UitlegLeg code en hulpmiddelen afzonderlijk vast
  6. 6
    VoorbeeldLees wat een bereik toestaat
  7. 7
    UitlegInstalleer de vastgelegde boom
  8. 8
    UitdagingInterpreteer een geblokkeerde schone installatie
  9. 9
    TipPlan een bewuste update
  10. 10
    UitdagingCombineer een bereik en een schone build
  11. 11
    SamenvattingLees de twee pakketbestanden samen
4

Controleer een project van bewerken tot build

15 stappen
Gebruik linten, opmaken, een voorbeeldweergave van productie en tests om verschillende soorten fouten te onderzoeken.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieStel elk hulpmiddel een andere vraag
  2. 2
    UitlegConfigureer een bruikbaar lintrapport
  3. 3
    VoorbeeldVind een typefout vóór de uitvoering
  4. 4
    UitdagingKies een opmaakcontrole
  5. 5
    VoorbeeldVoer ontwikkeling, build en voorbeeldweergave uit
  6. 6
    VoorbeeldVolg een buildoptimalisatie
  7. 7
    VerbandVerbind uitvoer met de broncode
  8. 8
    UitdagingKies wat je opnieuw bouwt
  9. 9
    VoorbeeldSchrijf een onafhankelijke verwachting
  10. 10
    KernpuntVergelijk inhoud en identiteit correct
  11. 11
    UitdagingTest de exacte grens
  12. 12
    TipWacht op een asynchrone test
  13. 13
    VoorbeeldGebruik een verstandige numerieke tolerantie
  14. 14
    UitdagingOnderzoek een geslaagde build met een verkeerd resultaat
  15. 15
    SamenvattingLees fouten als bewijs
5

Pas typen en componenten in een werkend project in

10 stappen
Onderscheid controleren van uitvoeren en bepaal daarna hoe projecthulpmiddelen een grotere gebruikersinterface ondersteunen.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieVoeg een hulpmiddel toe voor een specifieke behoefte
  2. 2
    VoorbeeldVind een aanroep met een verkeerd type
  3. 3
    UitlegScheid transformatie van controle
  4. 4
    UitdagingControleer gegevens die tijdens de uitvoering binnenkomen
  5. 5
    UitlegPlaats een component in de werkwijze
  6. 6
    VoorbeeldLees het takenmenu van het project
  7. 7
    UitdagingKies wanneer een framework helpt
  8. 8
    UitdagingVind de ontbrekende controle
  9. 9
    TipVoer controle geleidelijk in
  10. 10
    SamenvattingVolg elk hulpmiddel naar het bewijs

Klassen en modules in JavaScript: oefenvragen

50 Oefenvragen in 5 sets

Set 1: Pas modules en herhaalbare projectinstellingen toe10 Oefenvragen

Vraag 1 van 10

Wat gebeurt er op de laatste regel?

class Meter {
  value = 2;
  read() { return this.value; }
}
const meter = new Meter();
const read = meter.read;
read();
  1. De aanroep geeft 2 terug omdat een methode toewijzen haar ontvangende object behoudt.
  2. De aanroep werpt een fout op omdat this bij de losgekoppelde aanroep undefined is.
  3. De aanroep geeft undefined terug omdat het klasseveld privé is.
  4. De aanroep werpt een fout op omdat instantiemethoden niet aan variabelen kunnen worden toegewezen.
Toon antwoordVerberg antwoord
Antwoord: B
De laatste aanroep heeft geen ontvangend object vóór de punt. Een klassenmethode wordt in strikte modus uitgevoerd, dus is this gelijk aan undefined en werpt het lezen van de eigenschap value een fout op. De functie toewijzen is toegestaan, maar bindt het oorspronkelijke object niet; een omhullende pijlfunctie of bind zou die verbinding behouden.

Vraag 2 van 10

Wat is het laatste resultaat?

const base = { unit: "cm" };
const sample = Object.create(base);
Object.hasOwn(sample, "unit");
  1. true
  2. "cm"
  3. undefined
  4. false
Toon antwoordVerberg antwoord
Antwoord: D
De eigenschap hoort bij base, het prototype, niet bij sample zelf. Object.hasOwn geeft daarom false terug, hoewel het lezen van sample.unit "cm" zou vinden. Bij toegang tot een eigenschap kunnen prototypes worden doorzocht, terwijl een eigendomscontrole dat bewust niet doet.

Vraag 3 van 10

Wat geeft de laatste expressie terug?

class Label {
  constructor(text) { this.text = text; }
  length() { return this.text.length; }
}
new Label("Orbit").length();
  1. 5
  2. 4
  3. undefined
  4. "Orbit"
Toon antwoordVerberg antwoord
Antwoord: A
new slaat "Orbit" op in de instantie en length() leest de tekst van die instantie. De string heeft vijf tekens, dus is het resultaat 5. Het is niet undefined: de constructor heeft de eigenschap toegewezen die de methode leest.

Vraag 4 van 10

Wat geeft import("./help.js") onmiddellijk terug?
  1. De als standaard geëxporteerde waarde van de module zelf.
  2. Een nieuwe naamruimte met synchrone uitvoering.
  3. Een promise voor het modulenaamruimteobject.
  4. Een array met alle geëxporteerde waarden.
Toon antwoordVerberg antwoord
Antwoord: C
Dynamische import geeft een promise terug, die na succesvol laden en uitvoeren wordt voltooid met de modulenaamruimte. De standaardexport wordt niet onmiddellijk teruggegeven. Wacht op de promise en selecteer daarna een benoemde eigenschap of default uit de naamruimte voordat je die functionaliteit gebruikt.

Vraag 5 van 10

Een stabiel pakket op versie 7.3.6 brengt een compatibele foutoplossing uit zonder nieuwe functie. Welke volgende versie past bij semantische versienummering?
  1. 7.4.0
  2. 7.3.7
  3. 8.0.0
  4. 7.3.6
Toon antwoordVerberg antwoord
Antwoord: B
Een compatibele foutoplossing verhoogt het patchnummer en geeft 7.3.7. Het aanlokkelijke 7.4.0 zou op een compatibele nieuwe functie duiden, die in deze situatie ontbreekt. Een ingrijpende wijziging zou het majornummer verhogen, terwijl hetzelfde nummer de nieuwe uitgave niet zou identificeren.

Vraag 6 van 10

Een project staat ~6.4.2 toe. Wat is de nieuwste toegestane stabiele versie uit 6.4.9, 6.5.0, 7.0.0 en 6.4.1?
  1. 6.4.9
  2. 6.5.0
  3. 7.0.0
  4. 6.4.1
Toon antwoordVerberg antwoord
Antwoord: A
Het tildebereik accepteert versies vanaf 6.4.2 en onder 6.5.0, dus voldoet 6.4.9. Een nieuwere minorversie zoals 6.5.0 zou binnen een geschikt caretbereik passen, maar overschrijdt de bovengrens van dit tildebereik. Versie 6.4.1 ligt onder het vereiste minimum.

Vraag 7 van 10

Welke taak schrijft in een Vite-project de geoptimaliseerde productiebestanden naar de gebruikelijke uitvoermap?
  1. npm run dev
  2. npm run preview
  3. npm install
  4. npm run build
Toon antwoordVerberg antwoord
Antwoord: D
De buildtaak schrijft geoptimaliseerde productie-uitvoer, normaal naar dist. De voorbeeldweergave biedt bestanden aan die al zijn gebouwd en vervangt dus niet het bouwen na een wijziging in de broncode. De ontwikkeltaak biedt broncode aan om te bewerken en de installatie bereidt pakketten voor in plaats van de applicatie-uitvoer.

Vraag 8 van 10

Een test roept een asynchrone loadItems() aan zonder erop te wachten. De testcallback eindigt; de promise wordt later succesvol voltooid met een nieuwe array. De bedoelde assertie gebruikt toBe(["x"]). Wat moet veranderen om de beloofde inhoud betrouwbaar te controleren?
  1. Laat de test direct terugkeren en gebruik toEqual(["x"]).
  2. Wacht in een asynchrone test op loadItems() en behoud toBe(["x"]).
  3. Wacht in een asynchrone test op loadItems() en gebruik toEqual(["x"]).
  4. Wacht niet op de aanroep en controleer de promise met toBe(["x"]).
Toon antwoordVerberg antwoord
Antwoord: C
De test moet op het asynchrone resultaat wachten en daarna de inhoud van de teruggegeven array met toEqual vergelijken. Alleen wachten zou nog steeds een identiteitscontrole tegen een afzonderlijke arrayliteral opleveren, die mislukt bij gelijke inhoud. Alleen de vergelijkingsmethode wijzigen zou niet verzekeren dat de test op het laden wacht.

Vraag 9 van 10

Een .ts-programma wordt in Node.js uitgevoerd door ondersteunde typesyntaxis te verwijderen. Waarom toont die geslaagde uitvoering niet aan dat alle gedeclareerde typen correct zijn?
  1. Node.js converteert elke binnenkomende waarde naar het gedeclareerde type.
  2. Typeannotaties blijven alleen actief tot de eerste functieaanroep.
  3. Typesyntaxis verwijderen haalt syntaxis weg zonder typen te controleren.
  4. Node.js controleert typen alleen voor code die browser-API's gebruikt.
Toon antwoordVerberg antwoord
Antwoord: C
Bij het verwijderen van typesyntaxis haalt Node ondersteunde syntaxis weg zodat JavaScript kan worden uitgevoerd; er vindt geen statische controle plaats. Een programma kan daardoor één pad uitvoeren ondanks typefouten in de broncode. Gebruik afzonderlijk een typecontrole; een geslaagde uitvoering levert alleen bewijs over het werk dat daadwerkelijk tijdens die uitvoering is gedaan.

Vraag 10 van 10

Een team installeert een componentframework, ESLint en een testrunner in een Vite-sjabloon. Alleen de oorspronkelijke ontwikkel- en buildscripts bestaan; er is geen lintconfiguratie of testcode. Welk werk is nog nodig om herhaalbare lint- en gedragscontroles te ondersteunen?
  1. Installeer de hulpmiddelen opnieuw globaal en vertrouw op het bestaande buildscript.
  2. Configureer linten, schrijf asserties en bied de controles aan als scripts.
  3. Voeg alleen scriptnamen toe en laat de pakketten het gedrag afleiden.
  4. Verplaats de hulpmiddelen naar uitvoeringsafhankelijkheden en bouw het sjabloon opnieuw.
Toon antwoordVerberg antwoord
Antwoord: B
Geïnstalleerde pakketten bieden uitvoerbare hulpmiddelen, maar leveren niet de lintinstellingen of verwachte gedragingen van het team. Voeg de configuratie en tests toe en daarna scripts die ze consequent uitvoeren. Scriptnamen alleen kunnen geen asserties maken en de productiebuild van het sjabloon toont niet aan dat de ontbrekende gedragscontroles slagen.
Set 2: Lees klassen, imports en projecttaken10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Een module exporteert een functie als standaardexport en exporteert ook LIMIT op naam. Hoe kan één declaratie de functie als calculate en de constante onder haar geëxporteerde naam importeren?
  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";
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een klasse declareert static created = 8;. Haar instantie is toegewezen aan batch en de klasse heet Batch. Hoe lees je de opgeslagen teller?
  1. Batch.created
  2. new Batch().created
  3. Batch.prototype.created
  4. batch.constructor.prototype.created
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Waarom faalt deze constructor en welke volgorde lost dat op?

class Item {
  constructor(code) { this.code = code; }
}
class Box extends Item {
  constructor(code) {
    this.open = false;
    super(code);
  }
}
new Box("K7");
  1. Een eigen veld code ontbreekt; wijs eerst this.code toe.
  2. De constructor is overgeërfd; verwijder de aanroep super(code).
  3. De ouderklasse krijgt een string; converteer eerst code.
  4. this wordt te vroeg gebruikt; roep eerst super(code) aan.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een module bevat alleen export default class Badge {}. Welke import bindt die klasse aan de lokale naam 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";
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een startbestand voor de browser bevat een import-declaratie, maar de scripttag heeft geen typeattribuut. Welke HTML-wijziging maakt het een ES-module?
  1. Voeg alleen defer toe aan de scripttag.
  2. Voeg alleen async toe aan de scripttag.
  3. Voeg type="module" toe aan de scripttag.
  4. Voeg type="text/javascript" toe aan de scripttag.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een project heeft "scripts": { "check": "eslint ." }. Welke opdracht voert die benoemde taak uit?
  1. npm check
  2. npm install check
  3. node check
  4. npm run check
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een project gebruikt een codeopmaker alleen tijdens de ontwikkeling. In welk onderdeel van package.json moet de directe pakketvermelding normaal worden vastgelegd?
  1. devDependencies
  2. dependencies
  3. scripts
  4. engines
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een ESLint-uitvoering meldt één waarschuwing en geen fouten onder de gewone afsluitinstellingen. Wat toont een succesvolle afsluiting aan over de code?
  1. Geen lintregel gaf een melding; de getoonde waarschuwing gaat alleen over opmaak.
  2. Al het gedrag is correct; de waarschuwing kan de uitvoering niet beïnvloeden.
  3. Geen regel op foutniveau faalde; de waarschuwing moet nog worden bekeken.
  4. De waarschuwing is opgelost; succesvol linten wijzigt altijd bestanden.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een functie geeft een nieuw gemaakte array terug met "a" en "b". Hoe moet een Vitest-test die inhoud vergelijken met een aparte arrayliteral?
  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);
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een functie die is gedeclareerd om getallen te accepteren, ontvangt ontlede servergegevens. Een Vite-build slaagt, maar het programma voegt tijdens de uitvoering een string samen waar een som was bedoeld. Het project heeft geen afzonderlijke taak voor typecontrole en geen gegevenscontrole tijdens de uitvoering. Welke wijzigingen pakken beide ongecontroleerde grenzen aan?
  1. Voer een typecontrole uit en valideer ontlede waarden vóór de berekening.
  2. Voer de codeopmaker uit en declareer de ontlede gegevens als numeriek.
  3. Voer een typecontrole uit en vertrouw elk getypeerd serverantwoord.
  4. Bekijk een productiebuild en verwijder de typeannotaties.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 3: Volg toestand, afhankelijkheden en buildgedrag10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Een setter accepteert alleen eindige getallen van 4 tot en met 9. De instantie slaat 6 op. De setter controleert invoer vóór de toewijzing en werpt bij een fout een uitzondering op. Welke waarde blijft over nadat een poging om "8" toe te wijzen is afgevangen en waarom?
  1. 8 blijft over omdat de bereikcontrole de string converteert.
  2. 6 blijft over omdat privévelden elke setteraanroep afwijzen.
  3. 9 blijft over omdat de setter ongeldige waarden begrenst op het maximum.
  4. 6 blijft over omdat de string niet door de controle op een eindig getal komt.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Wat zijn de uiteindelijke waarden?

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]
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Wat zijn de laatste twee waarden?

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]
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een gewone browsermodule importeert "tiny-calendar". Het pakket is lokaal geïnstalleerd, maar de browser meldt een moduleaanduiding die niet kan worden opgelost. Welk soort ontbrekende configuratie verklaart dit?
  1. Een koppeling of hulpmiddel dat de naam zonder pad oplost naar code die de browser kan laden.
  2. Een tweede installatie die het pakket naar globale variabelen kopieert.
  3. Een CommonJS-type-instelling die de browser in node_modules laat zoeken.
  4. Een attribuut async dat het oplossen van de naam uitstelt tot na het ontleden.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

main.js importeert statisch config.js, dat op een netwerkantwoord wacht voordat het instellingen exporteert. Een onafhankelijke startmodule clock.js importeert geen van beide bestanden. Later voert de asynchrone eventhandler van main const plugin = await import("./plugin.js") uit. De enige export van die module is de standaardklasse Plugin. Welke beschrijving van het wachten en construeren is correct?
  1. Beide startmodules wachten op config; construeer met new plugin.default().
  2. Main wacht op config; clock gaat verder; construeer met new plugin().
  3. Geen startmodule wacht op config; construeer met new plugin.Plugin().
  4. Main wacht op config; clock gaat verder; construeer met new plugin.default().
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Overeenkomende pakketbestanden declareren ^8.1.0 en leggen een afhankelijkheid vast op 8.1.3. Een schone build voert npm ci uit nadat 8.7.0 is gepubliceerd. Welke versie wordt geïnstalleerd?
  1. 8.7.0
  2. 8.1.0
  3. 8.1.3
  4. De nieuwste 9.x-versie.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een ontwikkelaar moet de bestaande Vite-productie-uitvoer via een lokale HTTP-server bekijken. Welke projecttaak doet dat normaal?
  1. npm run dev
  2. npm run preview
  3. npm run build
  4. npm init -y
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een startmodule importeert één zuivere hulpfunctie uit een module die twee hulpfuncties exporteert en ook een vereiste registratie op het hoogste niveau uitvoert. Een Vite-productiebuild minificeert uitvoer en bevat een functie die pas wordt geladen wanneer die nodig is. Welke bewering over de uitvoer is gerechtvaardigd?
  1. Ongebruikte hulpcode kan worden verwijderd, vereiste registratie behouden en later geladen code afgesplitst.
  2. Alle niet-geïmporteerde code, inclusief registratie, moet verdwijnen in één direct geladen bestand.
  3. Beide hulpfuncties moeten blijven, registratie wordt verwijderd en later geladen code wordt ingevoegd.
  4. Elk bronbestand moet één uitvoerbestand worden waarin alle oorspronkelijke namen behouden blijven.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Welke opdracht controleert een TypeScript-project zonder gegenereerd JavaScript te schrijven?
  1. vite build
  2. node app.ts
  3. prettier . --check
  4. tsc --noEmit
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een applicatie roept een functie voor datumopmaak aan wanneer die nodig is. Een gebruikersinterfacesysteem roept daarentegen de componentcode van de applicatie aan wanneer renderen nodig is. Welk onderscheid illustreren deze voorbeelden?
  1. Een bibliotheek levert aanroepbare hulpfuncties; een framework coördineert aanroepen van applicatiecode.
  2. Een framework levert aanroepbare hulpfuncties; een bibliotheek coördineert al het renderen van de applicatie.
  3. Een bibliotheek vervangt modules; een framework vervangt pakketinstallatie en builds.
  4. Een framework controleert typen tijdens de uitvoering; een bibliotheek controleert typen alleen tijdens de ontwikkeling.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 4: Analyseer klassen en projectfouten10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Wat zijn de uiteindelijke waarden?

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]
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een klasse slaat haar enige toestand op in het privéveld #level en biedt een publieke getter op haar prototype. De klasse definieert geen methode toJSON. Wat levert JSON.stringify(new Gauge()) op?
  1. "{\"level\":0}"
  2. "{\"#level\":0}"
  3. "{}"
  4. undefined
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

class Photo extends Asset {} is gedeclareerd zonder constructor. Asset slaat het argument op dat aan zijn constructor wordt doorgegeven. Wat gebeurt er met een argument in new Photo("P8")?
  1. Het wordt weggegooid omdat de constructor van de subklasse ontbreekt.
  2. De standaardconstructor van de subklasse geeft het door aan Asset.
  3. Het wordt een statisch veld op de klasse Photo.
  4. Het wordt alleen opgeslagen als Photo elke overgeërfde methode overschrijft.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een module exporteert let count = 1, een object state = { count: 1 } en advance(), dat beide tellers verhoogt. Twee andere modules importeren dezezelfde exports. De eerste roept advance() aan en wijst daarna state.count = 9 toe. Wat leest de tweede als [count, state.count] en kan die count opnieuw toewijzen?
  1. De tweede leest [1, 1] en kan haar privé geïmporteerde kopie opnieuw toewijzen.
  2. De tweede leest [2, 2] en kan beide geïmporteerde bindingen opnieuw toewijzen.
  3. De tweede leest [1, 9] en kan wijzigingen van geëxporteerde primitieve waarden niet zien.
  4. De tweede leest [2, 9] en kan de geïmporteerde count niet opnieuw toewijzen.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een module declareert save() en een knop gebruikt inline onclick="save()". De module laadt correct, maar bij klikken verschijnt de melding dat save ongedefinieerd is. Hoe moet het event worden gekoppeld?
  1. Voeg defer toe en laat de inline eventhandler ongewijzigd.
  2. Koppel save vanuit de module met addEventListener.
  3. Exporteer save en verwacht dat HTML de naam automatisch importeert.
  4. Hernoem het bestand naar .mjs en behoud de inline eventhandler.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

De scripts van een project bevatten "inspect": "eslint src". Welke opdracht voert dat script uit met het ESLint-argument --fix?
  1. npm run inspect -- --fix
  2. npm run inspect --fix
  3. npm install inspect -- --fix
  4. npm inspect src --fix
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een gedeelde ESLint-configuratie dwingt een stijl voor aanhalingstekens af die tegengesteld is aan die van Prettier. In opgeslagen bestanden wisselen de aanhalingstekens steeds heen en weer. De code geeft ook een ongedefinieerde naam terug die no-undef activeert. Welke configuratie verwijdert het opmaakconflict met behoud van de nuttige foutcontrole?
  1. Schakel stijlregels en no-undef uit en gebruik daarna één codeopmaker.
  2. Behoud conflicterende stijlregels en no-undef en gebruik daarna één codeopmaker.
  3. Schakel conflicterende stijlregels uit, behoud no-undef en gebruik één codeopmaker.
  4. Schakel stijlregels uit, behoud no-undef en behoud concurrerende codeopmakers.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Wat voor soort wijziging brengt de opdracht --write van Prettier rechtstreeks aan?
  1. De verwachte resultaten die in gedragsasserties zijn opgeslagen.
  2. Onjuiste variabelenamen die uit uitvoeringsgegevens worden afgeleid.
  3. De gepubliceerde versies die door versiebereiken van afhankelijkheden zijn toegestaan.
  4. Spaties en opmaak in ondersteunde bronbestanden.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een controle moet eindige numerieke lengtes van 0 tot en met 12 cm accepteren. Welke drie testverwachtingen brengen verschillende fouten in deze implementatie aan het licht?

function setLength(n) {
  if (n <= 0 || n > 12) throw new RangeError();
  return n;
}
  1. Accepteer 0; wijs “7” af; wijs NaN af.
  2. Accepteer 12; wijs “7” af; wijs NaN af.
  3. Accepteer 0; accepteer “7”; wijs NaN af.
  4. Accepteer 0; wijs “7” af; accepteer NaN.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een statische site gebruikt npm-hulpmiddelen om browseruitvoer te bouwen. Wat is de rol van de map dist in die werkwijze?
  1. Bronconfiguratie die vóór elke build moet worden bewerkt.
  2. Het exacte afhankelijkheidsbestand dat het npm-vergrendelingsbestand vervangt.
  3. Gegenereerde uitvoer die door een geschikte statische host kan worden aangeboden.
  4. Geïnstalleerde ontwikkeltools die elke browser afzonderlijk downloadt.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 5: Combineer de ideeën in onbekende projecten10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Wat geeft new LoudNote("A").describe() terug?

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!?]"
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Wat geeft de laatste aanroep terug?

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
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

feature.js heeft een standaardexport en de benoemde export ready. Een herexportverzamelbestand bevat alleen export * from "./feature.js";. Wat geeft het herexportverzamelbestand door?
  1. Beide exports, waarbij de standaardexport wordt hernoemd naar feature.
  2. De benoemde export ready, zonder de standaardexport door te geven.
  3. Alleen de standaardexport, waarbij benoemde exports privé blijven.
  4. Geen van beide exports, omdat een herexportverzamelbestand ze moet uitvoeren door functies aan te roepen.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een gegevensmodule importeert op het hoogste niveau een module voor de gebruikersinterface om direct te renderen. De gebruikersinterface importeert de gegevensmodule en leest een niet-geïnitialiseerde binding. Unittests die de gegevens importeren, proberen in Node.js ook document te benaderen. Welke herstructurering pakt beide fouten aan?
  1. Verplaats eventkoppelingen naar de startmodule en houd gedeelde gegevenslogica onafhankelijk van de gebruikersinterface.
  2. Stel dezelfde circulaire imports uit met een timer en voeg een globale documentnaam toe.
  3. Plaats alle gedeelde definities in een groter herexportverzamelbestand en behoud renderen tijdens de import.
  4. Vang elke importfout af en voer de ongewijzigde interfacemodule opnieuw uit totdat die initialiseert.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Wat voorkomt "private": true in package.json rechtstreeks?
  1. Dat andere modules de geëxporteerde functies importeren.
  2. Dat browsergebruikers de gebouwde bronbestanden lezen.
  3. Dat het pakket per ongeluk via npm wordt gepubliceerd.
  4. Dat npm de ontwikkelafhankelijkheden van het project installeert.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een project declareert ^0.6.2, legt 0.6.4 vast en heeft een geldig overeenkomend vergrendelingsbestand. Het register biedt 0.6.9 en 0.7.0. Welke volgorde beschrijft de versie na npm ci en daarna de nieuwste toegestane versie na een bewuste npm update?
  1. Eerst 0.6.9, daarna 0.7.0.
  2. Eerst 0.6.4, daarna 0.6.9.
  3. Eerst 0.6.4, daarna 0.7.0.
  4. Eerst 0.6.2, daarna 0.6.4.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een front-endbronbestand leest een geheim toegangsgegeven uit een eigen VITE_-variabele. Waarom is dat gegeven zelfs na minificatie ongeschikt voor deze plek?
  1. De variabele bestaat alleen in de editor en verdwijnt vóór het bouwen.
  2. Het voorvoegsel versleutelt de waarde alleen zolang de ontwikkelmodus actief is.
  3. De waarde is beschermd tenzij ook een sourcemap wordt gepubliceerd.
  4. De beschikbaar gemaakte waarde wordt naar browsergebruikers gestuurd en kan worden bekeken.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een functie moet een lege naam afwijzen door RangeError op te werpen. Met welke Vitest-assertie kan de vergelijkingsmethode de uitzondering waarnemen?
  1. expect(() => createName("")).toThrow(RangeError);
  2. expect(createName("")).toThrow(RangeError);
  3. expect(() => createName("")).toBe(RangeError);
  4. expect(createName).toEqual(new RangeError());
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een klasse gebruikt TypeScript private value, wijst er ontlede netwerkinvoer aan toe en geeft met de verkeerde formule een numeriek resultaat terug. Het project slaagt voor tsc --noEmit. Welke combinatie pakt afscherming tijdens de uitvoering, externe invoer en gedrag aan?
  1. Behoud het sleutelwoord private, bevestig het antwoordtype en herhaal de formule in tests.
  2. Gebruik een JavaScript-veld met #, valideer invoer en test onafhankelijk verwachte resultaten.
  3. Gebruik een JavaScript-veld met #, vertrouw de antwoordannotatie en voer opmaak uit.
  4. Valideer invoer, schakel controle uit met any en vertrouw op een geslaagde build.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een componentproject wordt met succes gebouwd, maar heeft gecoördineerde pagina-URL's en op de server gerenderde initiële HTML nodig. Welke bredere projectlaag biedt gewoonlijk beide functies rond de gebruikersinterface met componenten?
  1. Een router aan de clientzijde die pas werkt nadat JavaScript is geladen.
  2. Een statische terugvalpagina zonder renderstap op de server.
  3. Een opslag voor componenttoestand zonder integratie met routering.
  4. Een metaframework met routering en renderen op de server.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Kom je niet uit je eigen opgave? Huiswerkhulp

Kernbegrippen

88 Kernbegrippen, elk met een definitie

A

actuele binding
Een actuele binding verbindt een geïmporteerde naam met de huidige waarde van de exporterende module, zodat wijzigingen door de exporteur zichtbaar blijven voor importeurs.
Wanneer een module een teller en een verhoogfunctie exporteert, leest een importeur de bijgewerkte teller via de geïmporteerde naam nadat de verhoogfunctie is uitgevoerd.
afhankelijkheid
Een afhankelijkheid is een pakket waarop het project steunt, waarbij pakketten voor de uitvoering normaal in het onderdeel dependencies van package.json worden vastgelegd.
Een datumbibliotheek die door de applicatie wordt aangeroepen, is een uitvoeringsafhankelijkheid, ook als die voor de browser wordt gebundeld.
assertie
Een assertie is een testinstructie die een specifieke verwachte eigenschap van een resultaat controleert en een fout meldt wanneer niet aan die verwachting is voldaan.
Een assertie kan controleren of een ongeldige zijlengte een uitzondering opwerpt in plaats van een bruikbare rechthoek te maken.
await op moduleniveau
Await op moduleniveau laat een ES-module tijdens de uitvoering buiten een functie wachten, waardoor modules die van die uitvoering afhankelijk zijn worden vertraagd.
Een instellingenmodule kan het ophalen van configuratie voltooien voordat de afhankelijke startmodule haar lichaam uitvoert.

B

benoemde export
Een benoemde export maakt een declaratie beschikbaar onder een bepaalde geëxporteerde naam die importeurs tussen accolades in een importdeclaratie opvragen.
Een module met grenzen exporteert MAX en een importeur kan die rechtstreeks opvragen of lokaal hernoemen.
beveiligingscontrole van afhankelijkheden
Een beveiligingscontrole van afhankelijkheden vergelijkt geïnstalleerde pakketversies met meldingen van bekende kwetsbaarheden en levert bevindingen op om te beoordelen en te verhelpen.
Lees een bevinding uit de beveiligingscontrole om te bepalen of de betreffende code wordt gebruikt en welke compatibele oplossingen bestaan.
bibliotheek
Een bibliotheek biedt herbruikbare code die applicatiecode aanroept wanneer die nodig is, waarbij het aanroepende programma de controle over die verzoeken houdt.
Een applicatie roept een hulpmethode voor datumopmaak aan wanneer zij een tijdstempel in de interface moet weergeven.
bundler
Een bundler volgt de afhankelijkheden van een programma en combineert of transformeert ze tot uitvoerbestanden die geschikt zijn om aan gebruikers aan te bieden.
Een browserbuild kan geïnstalleerde pakketten oplossen en geoptimaliseerde bestanden naar de gegenereerde map dist schrijven.

C

circulaire afhankelijkheid
Een circulaire afhankelijkheid is een importcyclus waarin modules rechtstreeks of via andere modules in de graaf van elkaar afhankelijk zijn.
Door een gedeelde hulpmethode uit een gegevensmodule en een rendermodule naar een derde, onafhankelijke module te verplaatsen, kun je de importcyclus ertussen verwijderen.
codeopmaker
Een codeopmaker herschrijft de opmaak van code op een consistente manier en regelt spaties, regeleinden, inspringing en andere ondersteunde stijlkeuzes.
Prettier kan spaties in een object standaardiseren zonder te bepalen of het object de juiste waarden bevat.
codeopsplitsing
Codeopsplitsing verdeelt gebouwde code in afzonderlijk laadbare stukken, zodat sommige functies later kunnen worden opgehaald in plaats van direct bij het opstarten.
Een dynamische import voor een zelden gebruikte editor kan een buildtool een grens geven voor later laden.
CommonJS
CommonJS is het oorspronkelijke modulesysteem van Node.js en gebruikt synchrone require-aanroepen en module.exports om waarden aan te bieden.
Een .cjs-bestand blijft CommonJS, ook wanneer het omringende pakket expliciet ES-modules selecteert.
component
Een component is een herbruikbaar deel van een gebruikersinterface dat opmaak en gedrag groepeert, vaak met stijlen en toestand die de weergegeven uitvoer beïnvloeden.
Een navigatiecomponent kan op meerdere pagina's verschijnen terwijl de interactiecode op één plek blijft.
compositie
Compositie bouwt gedrag op door een object andere objecten te geven waaraan het werk overdraagt, waarmee een “heeft een”-relatie tussen die objecten wordt uitgedrukt.
Een rapport bevat een meldingssysteem en vraagt dat om een bericht te sturen zonder zelf een soort meldingssysteem te worden.
constructor
Een constructor is de speciale klassenmethode die wordt uitgevoerd wanneer een nieuwe instantie wordt gemaakt en die het object initialiseert met opgegeven argumenten.
Een rechthoekconstructor slaat breedte en hoogte op zodat latere methodeaanroepen de oppervlakte kunnen berekenen.
constructorfunctie
Een constructorfunctie is een functie die met new wordt gebruikt om objecten te initialiseren, vaak samen met methoden die aan haar prototype worden toegewezen.
Oudere JavaScript-code kan area aan Rectangle.prototype koppelen nadat een constructorfunctie is gedefinieerd.

D

dynamische import
Een dynamische import is een import()-expressie die een module laadt wanneer die nodig is en een promise voor de modulenaamruimte teruggeeft.
Een asynchrone knopeventhandler kan een optionele grafiek pas laden wanneer de gebruiker vraagt die weer te geven.

E

eigen eigenschap
Een eigen eigenschap is rechtstreeks op een object opgeslagen, anders dan een overgeërfde eigenschap die via een van de prototypeverwijzingen beschikbaar is.
De breedte van een rechthoek kan een eigen eigenschap zijn, ook al is de gewone oppervlaktemethode overgeërfd.
ES-module
Een ES-module is een JavaScript-module die de standaard syntaxis import en export gebruikt en een eigen bereik en regels voor strikte uitvoering heeft.
Een vormenmodule kan meetkundige hulpfuncties importeren zonder hun namen in het globale bereik van de pagina te plaatsen.

F

framework
Een framework biedt een applicatiestructuur en coördineert wanneer door de gebruiker aangeleverde code binnen die structuur wordt uitgevoerd.
Een framework voor gebruikersinterfaces kan componentcode aanroepen wanneer veranderende toestand vereist dat de weergegeven interface wordt bijgewerkt.

G

getter
Een getter is een accessormethode die wordt uitgevoerd wanneer een eigenschap wordt gelezen en waarmee een waarde zonder aanroephaakjes kan worden berekend of beschikbaar gemaakt.
Het lezen van thermostat.target kan een getter aanroepen die de opgeslagen privédoeltemperatuur teruggeeft.
grenswaardetest
Een grenswaardetest controleert gedrag op een exacte grens of net daarbuiten en brengt zo fouten in inclusieve of exclusieve vergelijkingen aan het licht.
Een bereik voor doelwaarden van 10 tot en met 30 °C heeft controles nodig op beide eindpunten en voor waarden net buiten elke toegestane grens.

H

herexport
Een herexport geeft exports van een andere module door via de huidige module, zodat een bestand een publieke interface kan verzamelen.
Een index van een map kan benoemde hulpfuncties doorgeven; een export-sterdeclaratie geeft hun standaardexport niet door.
herexportverzamelbestand
Een herexportverzamelbestand verzamelt herexports van meerdere modules op één importlocatie, zodat hun gedeelde interface gemakkelijker bereikbaar is.
Een groot herexportverzamelbestand kan een circulaire afhankelijkheid verbergen wanneer een module via de index van haar eigen map importeert.

I

importmap
Een importmap is een browserconfiguratie die moduleaanduidingen aan URL's koppelt, zodat moduleimports namen kunnen gebruiken die de browser niet zelf kan oplossen.
Een pagina plaatst haar importmap vóór haar modulescripts om een korte pakketnaam aan een server-URL te koppelen.
inhoudshash
Een inhoudshash in een bestandsnaam verandert met de inhoud van het bestand en helpt caches een nieuw bestand van een oudere versie te onderscheiden.
Een gewijzigd buildbestand krijgt een nieuwe naam met een hash, zodat browsers het kunnen opvragen terwijl ze ongewijzigde bestanden cachen.
inkapseling
Inkapseling houdt interne toestand achter een gecontroleerde publieke interface waarvan de bewerkingen de regels voor geldige wijzigingen bewaken.
Een thermostaat laat aanroepende code een wijziging van de doelwaarde aanvragen, terwijl de setter bepaalt of de invoer geldig is.
instantie
Een instantie is een afzonderlijk object dat op basis van een klasse is gemaakt, met een eigen toestand en toegang tot het gedrag dat die klasse biedt.
Twee rechthoekinstanties kunnen een oppervlaktemethode delen terwijl ze verschillende afmetingen in centimeters opslaan.
instantieveld
Een instantieveld is een eigenschap die voor elk object van een klasse wordt gedeclareerd en elke instantie een eigen opgeslagen waarde geeft.
Een tellerveld dat op nul is geïnitialiseerd, begint afzonderlijk op elk nieuw gemaakt tellerobject.
interface
Een interface beschrijft een verwachte objectstructuur voor TypeScript-controle, inclusief de eigenschappen en methoden die die structuur vereist.
Een interface voor vormen kan een naam en een oppervlaktemethode vereisen zonder de implementatie van de klasse te leveren.

K

klasse
Een klasse is een sjabloon om met constructors, velden en methoden objecten met een gemeenschappelijke structuur en gedeeld gedrag te maken.
Een klasse Rectangle kan meerdere vormen maken waarvan de oppervlaktemethoden hun eigen breedte en hoogte gebruiken.

L

linter
Een linter analyseert broncode aan de hand van geconfigureerde regels om waarschijnlijke fouten of riskante patronen te melden zonder het programma uit te voeren.
ESLint kan een verkeerd gespelde variabele die wordt teruggegeven opsporen, ook wanneer geen test de betreffende functie aanroept.

M

meldingsniveau van een regel
Het meldingsniveau van een regel bepaalt of een lintregel is uitgeschakeld, een waarschuwing meldt of een fout meldt die de opdracht normaal laat mislukken.
Een waarschuwing over een ongebruikte variabele kan verschijnen bij een succesvolle uitvoering, terwijl een fout over een ongedefinieerde naam die laat mislukken.
metaframework
Een metaframework voegt bredere applicatiefuncties toe rond een ecosysteem voor gebruikersinterfaces, gewoonlijk waaronder routering, renderen op de server en een buildconfiguratie.
Een project kan zo'n laag kiezen wanneer het zowel paginanavigatie als op de server gerenderde weergaven nodig heeft.
methode
Een methode is een functie die wordt aangeboden als onderdeel van de interface van een object of klasse en meestal werkt op het object dat de aanroep ontvangt.
De aanroep tile.area() laat de methode de afmetingen van tile lezen via het ontvangende object this.
methodeoverschrijving
Een methodeoverschrijving is een methode van een subklasse die een overgeërfde methode met dezelfde naam vervangt voor aanroepen die het gedrag van die subklasse selecteren.
Een cirkel overschrijft area() en blijft de gedeelde beschrijvingsmethode van de ouderklasse overerven.
minificatie
Minificatie verkleint gegenereerde code door onnodige opmaak te verwijderen en namen waar mogelijk in te korten, zonder het bedoelde gedrag te veranderen.
Een productiebestand kan kortere lokale namen hebben, ook al gebruikte de broncode beschrijvende identifiers.
mixin
Een mixin is een herbruikbare verzameling methoden die naar een klasse of prototype wordt gekopieerd om gedrag toe te voegen zonder een andere superklasse te kiezen.
Een mixin voor serialisatie kan via prototypes hulpmethoden leveren aan verder niet-verwante klassen.
moduleaanduiding
Een moduleaanduiding is de string die de door een import gevraagde module identificeert, zoals een relatief pad, een URL of een pakketnaam.
De aanduiding "../utils.js" vraagt de lader om een module één map boven het importerende bestand.
moduleaanduiding zonder pad of URL
Een moduleaanduiding zonder pad of URL noemt een pakket zonder padvoorvoegsel of volledige URL, waardoor de omgeving of hulpmiddelen die naam moeten oplossen.
Node.js kan een geïnstalleerde pakketnaam oplossen die een gewone browser zonder extra koppeling niet kan vinden.
modulenaamruimte
Een modulenaamruimte is een object dat de exports van een module als eigenschappen beschikbaar maakt, inclusief default wanneer een standaardexport bestaat.
Wachten op een dynamische import geeft een naamruimte waaruit de aanroeper de geëxporteerde constructor selecteert.
modulevervanging tijdens uitvoering
Modulevervanging tijdens uitvoering werkt een gewijzigde module in een draaiende applicatie bij, vaak met behoud van ondersteunde toestand zonder de pagina volledig te herladen.
Het bewerken van een component kan het weergegeven gedrag bijwerken terwijl de huidige toestand van de interface intact blijft.

N

neveneffect
Een neveneffect is waarneembaar werk naast het teruggeven van een waarde, zoals gedeelde toestand wijzigen, de pagina bijwerken of gedrag registreren.
Een module die de pagina tijdens het importeren wijzigt, is moeilijker te testen zonder browseromgeving.
npm
npm is de pakketbeheerder die bij Node.js wordt geleverd en bestaat uit een opdrachtregelprogramma en een bijbehorend openbaar pakketregister.
Een project gebruikt npm om afhankelijkheden te installeren en de opdrachten uit te voeren die in de pakketscripts zijn vastgelegd.
npm-script
Een npm-script is een benoemde opdracht in package.json die een projecttaak een herhaalbaar toegangspunt geeft via de npm-opdrachtregel.
Het lintscript kan het lokaal geïnstalleerde hulpmiddel van het project uitvoeren wanneer een teamgenoot npm run lint uitvoert.
npx
npx is een opdrachtuitvoerder die een geïnstalleerd uitvoerbaar pakketprogramma kan gebruiken of kan aanbieden een pakketopdracht tijdelijk te downloaden en uit te voeren.
Een ontwikkelaar kan een opdracht voor een statische server uitproberen zonder die als permanente afhankelijkheid van het project toe te voegen.

O

ontvangend object
Een ontvangend object is het object waarop een methode wordt aangeroepen en dat normaal de waarde van this levert bij een gewone methodeaanroep.
In box.open() is het ontvangende object box; open loskoppelen bindt dat ontvangende object niet blijvend.
ontwikkelafhankelijkheid
Een ontwikkelafhankelijkheid is een pakket dat nodig is om een project te ontwikkelen, controleren of bouwen, en niet om als bibliotheekcode tijdens de uitvoering te dienen.
Een codeopmaker of testrunner wordt meestal met -D geïnstalleerd zodat de versie voor het project wordt vastgelegd.
ontwikkelserver
Een ontwikkelserver biedt tijdens het bewerken een project lokaal aan en kan imports oplossen, broncode transformeren en de pagina bijwerken wanneer bestanden veranderen.
Een Vite-ontwikkelserver toont een lokaal HTTP-adres waarmee de browser de applicatie in ontwikkeling laadt.
opsombare eigenschap
Een opsombare eigenschap heeft een vlag waardoor zij kan verschijnen in opsombewerkingen die opsombare sleutels selecteren.
Object.keys somt eigen opsombare stringsleutels op, terwijl for...in ook overgeërfde sleutels kan meenemen.
overerving
Met overerving kan een subklasse voortbouwen op het gedrag van een ouderklasse, waarmee een “is een”-relatie tussen de gemodelleerde soorten objecten wordt uitgedrukt.
Een cirkel erft de beschrijving van een vorm over maar levert een berekening die geschikt is voor de eigen oppervlakte.
overgeërfde eigenschap
Een overgeërfde eigenschap wordt via de prototypeketen van een object gevonden in plaats van als eigen eigenschap op dat object te zijn opgeslagen.
Een instellingenobject kan een standaardthema lezen terwijl Object.hasOwn meldt dat het geen eigen themasleutel heeft.
overschaduwing
Overschaduwing ontstaat wanneer een eigen eigenschap tijdens het gewone opzoeken van eigenschappen een overgeërfde eigenschap met dezelfde naam verbergt.
Als je de eigen lettergrootte van een object verwijdert, kan de ongewijzigde standaardgrootte op zijn prototype weer zichtbaar worden.

P

pakket
Een pakket is een map die wordt beschreven door een package.json-bestand, dat de identiteit vastlegt en scripts en afhankelijkheden kan beschrijven.
Een lokale applicatie kan een npm-pakket zijn, ook wanneer de vlag private publicatie in het register voorkomt.
polymorfisme
Polymorfisme laat dezelfde methodeaanroep via een gedeelde interface verschillende implementaties selecteren voor verschillende ontvangende objecten.
Eén lus roept describe() aan op cirkels en rechthoeken en elk object levert de juiste oppervlakte.
privémethode
Een privémethode is intern klassegedrag met een naam die # bevat en houdt hulpbewerkingen buiten de publieke interface van het object.
Een klasse kan this.#check(value) aanroepen om invoer te valideren zonder die hulpmethode beschikbaar te maken aan externe code.
privéveld
Een privéveld is opslag die in een klasse is gedeclareerd met een naam die met # begint en die alleen rechtstreeks toegankelijk is binnen de klasse die de naam declareert.
Een kindklasse gebruikt de publieke getter van haar ouderklasse in plaats van rechtstreeks een privéveld voor de doelwaarde te benoemen dat de ouderklasse declareert.
prototype
Een prototype is een object dat aan een ander object is gekoppeld en wordt doorzocht wanneer dat object een gevraagde eigen eigenschap niet heeft; de koppeling kan ook naar null verwijzen.
Een instantie kan een gedeelde oppervlaktemethode op het prototype van haar klasse vinden zonder een eigen kopie van de methode op te slaan.
prototypeketen
Een prototypeketen is de reeks verwijzingen die wordt gevolgd bij het opzoeken van eigenschappen en eindigt bij null wanneer er geen volgend prototype bestaat.
Een cirkel kan zijn beschrijving op Shape.prototype vinden nadat de zoekactie via Circle.prototype is gegaan.
publieke interface
Een publieke interface is de verzameling toegankelijke bewerkingen waarmee andere code een object gebruikt zonder afhankelijk te zijn van de interne opslag.
Aanroepende code kan de doelwaarde van een thermostaat instellen, ook als de klasse later verandert hoe zij die waarde opslaat.

S

schone installatie
Een schone installatie maakt de vastgelegde afhankelijkheidsboom opnieuw met npm ci, vereist een overeenkomend vergrendelingsbestand en vervangt bestaande geïnstalleerde pakketten.
Als de pakketbeschrijving en het vergrendelingsbestand niet overeenkomen, mislukt een schone installatie in plaats van ze ongemerkt te herschrijven.
semantische versienummering
Semantische versienummering geeft uitgaven een nummer als MAJOR.MINOR.PATCH om ingrijpende wijzigingen, compatibele functies en compatibele foutoplossingen te onderscheiden.
Een stabiele uitgave die een compatibele functie toevoegt, gaat van 2.4.1 naar 2.5.0 in plaats van naar een nieuwe majorversie.
setter
Een setter is een accessormethode die wordt uitgevoerd wanneer een waarde aan een eigenschap wordt toegewezen en die validatie mogelijk maakt voordat de opslag verandert.
Een setter voor de doelwaarde kan een temperatuur buiten het bereik afwijzen voordat die aan een privéveld wordt toegewezen.
sourcemap
Een sourcemap verbindt posities in gegenereerde code met posities in oorspronkelijke bronbestanden, waardoor getransformeerde uitvoer gemakkelijker te debuggen is.
Een aanroepspoor kan naar de oorspronkelijke functie verwijzen wanneer de browser de bijbehorende sourcemap beschikbaar heeft.
standaardexport
Een standaardexport biedt de enkele standaardwaarde van een module, die zonder accolades wordt geïmporteerd onder een lokale naam die de importeur kiest.
Een als standaard geëxporteerde klasse kan als Circle worden geïmporteerd, ook als een ander bestand haar een andere lokale naam geeft.
statisch initialisatieblok
Een statisch initialisatieblok is een blok binnen een klasse dat tijdens de klassendefinitie één keer wordt uitgevoerd om initialisatie op klasseniveau te verzorgen.
Een klasse kan een gedeelde opzoektabel in een statisch blok vullen zonder die initialisatie voor elk object te herhalen.
statisch lid
Een statisch lid is een veld of methode dat bij de klasse zelf hoort en via de klasse wordt benaderd in plaats van via een afzonderlijke instantie.
Een gedeelde teller voor gemaakte objecten wordt van de klasse gelezen, terwijl elk object zijn eigen instantiegegevens behoudt.
statische analyse
Statische analyse inspecteert code zonder die uit te voeren en gebruikt de geschreven structuur en geconfigureerde regels om mogelijke problemen te herkennen.
Een melding over een ongedefinieerde naam kan in de editor verschijnen voordat de applicatie die regel uitvoert.
statische fabrieksmethode
Een statische fabrieksmethode is een methode op klasseniveau die instanties maakt en teruggeeft via een naam die een bepaalde constructiekeuze beschrijft.
Een rechthoekklasse kan Rectangle.square(5) aanbieden om een instantie met gelijke zijden te maken.
subklasse
Een subklasse is een met extends gedeclareerde klasse die van één superklasse overerft en leden kan toevoegen of overgeërfd gedrag kan specialiseren.
Een subklasse voor vierkanten kan dezelfde zijlengte twee keer doorgeven aan de constructor van de rechthoek als ouderklasse.
superklasse
Een superklasse is de ouderklasse waarvan een subklasse overerft en die initialisatie en gedrag biedt die beschikbaar zijn voor afgeleide instanties.
De superklasse voor vormen slaat de gemeenschappelijke naam op die haar subklassen gebruiken wanneer ze hun beschrijvingen maken.

T

testgestuurde ontwikkeling
Testgestuurde ontwikkeling begint met een gedragstest die mislukt, voegt genoeg implementatie toe om de test te laten slagen en verbetert daarna de code terwijl de tests blijven slagen.
Een nieuwe validatieregel kan eerst worden uitgedrukt als een test die mislukt, voordat de controle wordt geïmplementeerd.
testrunner
Een testrunner vindt tests en voert ze uit, rapporteert de resultaten en geeft normaal een afsluitcode voor mislukking terug wanneer een test mislukt.
Een projectscript kan de Node.js-testrunner of Vitest aanroepen voordat wijzigingen met een teamgenoot worden gedeeld.
toestand
Toestand bestaat uit de gegevens die de huidige situatie van een interface weergeven. Veranderingen in die gegevens kunnen het gebruikersinterfacesysteem laten bijwerken wat gebruikers zien.
Als de geselecteerde taak verandert, kunnen meerdere weergaven worden bijgewerkt die allemaal van die gedeelde toestand afhankelijk zijn.
tolerantie
Een tolerantie is een toegestaan numeriek verschil waarmee je benaderde resultaten kunt vergelijken zonder fouten buiten de gekozen grens te accepteren.
Een test met drijvendekommagetallen kan een heel klein afrondingsverschil toestaan en tegelijk een onjuiste oppervlakteformule afwijzen.
transitieve afhankelijkheid
Een transitieve afhankelijkheid is een pakket dat indirect nodig is omdat een van de afhankelijkheden van het project, of een van hun afhankelijkheden, het nodig heeft.
Het vergrendelingsbestand legt geneste pakketten vast, ook wanneer de applicatie die pakketten nooit rechtstreeks importeert.
typeannotatie
Een typeannotatie geeft in de broncode aan welk soort waarde of welke structuur wordt verwacht en levert informatie voor statische controle.
Een annotatie voor een numerieke parameter helpt een editor een niet-passende aanroep af te wijzen voordat de functie wordt uitgevoerd.
typedefinitie
Een typedefinitie beschrijft voor hulpmiddelen de typen van bestaande code en wordt vaak geleverd via .d.ts-bestanden of afzonderlijke definitiepakketten.
Een JavaScript-bibliotheek kan informatie voor automatische aanvulling en controle in de editor leveren zonder haar uitvoeringscode te herschrijven.
TypeScript
TypeScript voegt statische typesyntaxis en typecontrole toe aan JavaScript, zodat onverenigbaar gebruik van waarden vóór de uitvoering kan worden ontdekt.
De typecontrole kan een string melden die wordt doorgegeven aan een parameter die als numeriek is gedeclareerd, ook als JavaScript die impliciet zou kunnen converteren.
typesyntaxis verwijderen
Typesyntaxis verwijderen haalt ondersteunde typesyntaxis weg om uitvoering mogelijk te maken zonder zelf te controleren of de typen consistent worden gebruikt.
Een TypeScript-bestand kan door het verwijderen van typesyntaxis in Node.js worden uitgevoerd, ook als een afzonderlijke typecontrole een fout zou melden.

U

uitgesteld script
Een uitgesteld script wacht met uitvoeren totdat de HTML is ontleed; gewone browsermodulescripts worden standaard uitgesteld.
Een gewone startmodule kan eventhandlers koppelen aan elementen die eerder in de voltooide HTML-pagina stonden.
unittest
Een unittest voert een klein deel van een programma uit met gecontroleerde invoer en controleert of het waargenomen gedrag overeenkomt met een verwacht resultaat.
Een rechthoektest kan een bekende oppervlakte controleren zonder de pagina te laden die de rechthoek weergeeft.

V

validatie tijdens uitvoering
Validatie tijdens uitvoering controleert werkelijke waarden terwijl het programma draait, vooral gegevens uit externe bronnen die typen niet kunnen inspecteren.
Ontlede netwerkgegevens hebben een controle nodig voordat een gedeclareerd numeriek veld in een berekening wordt vertrouwd.
vergrendelingsbestand
Een vergrendelingsbestand legt de exacte gekozen afhankelijkheidsboom vast zodat installaties versies kunnen reproduceren zonder telkens nieuwe keuzes op te lossen.
Een build gebruikt overeenkomende pakketbestanden met npm ci om de vastgelegde boom op een andere computer opnieuw te maken.
versiebereik
Een versiebereik beschrijft de uitgaven die een afhankelijkheidsvermelding toestaat en kan ruimer zijn dan de exacte versie die momenteel is geïnstalleerd.
Een caretbereik kan een nieuwere minoruitgave toestaan terwijl een schone installatie nog steeds een oudere vastgelegde keuze volgt.
verwijdering van ongebruikte code
Verwijdering van ongebruikte code haalt code weg waarvan buildanalyse kan bewijzen dat die ongebruikt is en veilig kan worden weggelaten, terwijl neveneffecten die moeten worden uitgevoerd behouden blijven.
Een ongebruikte zuivere hulpmethode kan uit de uitvoer verdwijnen terwijl een andere hulpmethode uit dezelfde module blijft.
vlakke configuratie
Vlakke configuratie is het huidige op JavaScript gebaseerde configuratieformaat van ESLint, dat configuratieobjecten en regelinstellingen combineert.
Een module eslint.config.js kan aanbevolen controles exporteren plus de globale namen die in browsercode beschikbaar zijn.
voorbereiden, uitvoeren en controleren
Voorbereiden, uitvoeren en controleren is een teststructuur waarin je invoer voorbereidt, het gedrag uitvoert en het resultaat met een verwachting vergelijkt.
Een test bouwt een rechthoek, roept de oppervlaktemethode aan en controleert daarna een onafhankelijk berekend resultaat.

Over deze les

Door StudeliFout melden

Maak je eigen Studiemateriaal

Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.

Aan de slag