- Leren
- Informatica & ICT
- Programmeren
- JavaScript programmeren: DOM, events, asynchrone code en modules
- JavaScript-objecten en JSON
JavaScript-objecten en JSON
BeginnerLes 4 van 9 in Cursus JavaScript programmeren: DOM, events, asynchrone code en modules
Wat je leert
- Beschrijf echte zaken in code als objecten met benoemde eigenschappen, lees en wijzig die eigenschappen en begrijp hoe objecten worden opgeslagen, gekopieerd en vergeleken.
- Maak objecten en werk met hun eigenschappenSchrijf objectliterals, lees eigenschappen met puntnotatie en blokhaaknotatie en voeg eigenschappen toe, wijzig ze en verwijder ze.
- Controleer de eigenschappen van een object en doorloop ze met een lusControleer of een eigenschap bestaat, maak lijsten van sleutels, waarden en sleutel-waardeparen en doorloop of transformeer de eigenschappen van een object.
- Begrijp referenties, kopiëren en vergelijkenLeg uit waarom objecten via referenties worden gedeeld, vergelijk objecten correct en maak oppervlakkige en diepe kopieën.
- Werk met geneste gegevensLees en verwerk objecten binnen objecten en arrays van objecten, vang ontbrekende onderdelen op met ?. en ?? en kies een structuur die bij de gegevens past.
- Maak objecten en werk met hun eigenschappen
- Schrijf methoden die de gegevens van hun object gebruiken, leg uit hoe het sleutelwoord this bij elke soort aanroep zijn waarde krijgt en behoud de juiste waarde van this wanneer je een methode doorgeeft.
- Schrijf methoden die de gegevens van hun object gebruikenDefinieer methoden met de verkorte notatie, gebruik this om het object te lezen en bij te werken en roep methoden correct aan.
- Leg uit hoe this zijn waarde krijgtBepaal de waarde van this aan de hand van de manier waarop een functie wordt aangeroepen en leg uit waarom pijlfuncties zich anders gedragen.
- Behoud de waarde van this wanneer je methoden als callbacks doorgeeftHerken wanneer een methode haar object verliest en los dit op met een omhullende pijlfunctie, bind, call of apply.
- Schrijf methoden die de gegevens van hun object gebruiken
- Haal waarden uit objecten en arrays met destructurering en kopieer, combineer en verzamel waarden met spreadsyntaxis en restsyntaxis.
- Destructureer objectenPak objecteigenschappen uit in variabelen, met hernoemen, standaardwaarden, geneste patronen en gedestructureerde functieparameters.
- Destructureer arrays en andere itereerbare waardenPak waarden uit op basis van hun positie, sla ze over of geef ze een standaardwaarde, verwissel variabelen en destructureer sleutel-waardeparen in lussen.
- Kopieer, voeg samen en verzamel met spreadsyntaxis en restsyntaxisGebruik spreadsyntaxis om objecten en arrays te kopiëren en samen te voegen en om arrayitems als argumenten door te geven, gebruik restsyntaxis om waarden te verzamelen en onderscheid de twee.
- Destructureer objecten
- Gebruik Map voor verzamelingen sleutel-waardeparen met sleutels van elk type en Set voor verzamelingen unieke waarden, en kies tussen deze structuren en gewone objecten en arrays.
- Sla sleutel-waardeparen op in een MapMaak een Map en werk die bij, doorloop de sleutel-waardeparen, converteer tussen Maps en objecten en bepaal wanneer een Map beter past dan een object.
- Bewaar unieke waarden in een SetMaak een Set en werk die bij, verwijder dubbele waarden uit arrays en vergelijk verzamelingen met verzamelingsoperaties.
- Sla sleutel-waardeparen op in een Map
- Lees en schrijf het JSON-tekstformaat, zet JavaScript-waarden met JSON.stringify om in JSON en JSON-tekst met JSON.parse terug in waarden, en handel gevallen af waarin de twee niet overeenkomen.
- Lees en schrijf het JSON-formaatHerken geldige JSON, leg uit hoe JSON verschilt van een JavaScript-objectliteral en herken veelvoorkomende syntaxisfouten.
- Zet waarden om in JSON-tekst met JSON.stringifyConverteer objecten en arrays naar JSON-strings, maak de uitvoer op, kies welke eigenschappen worden opgenomen en voorspel wat wegvalt of verandert.
- Zet JSON-tekst om in waarden met JSON.parseOntleed JSON veilig, herstel waarden zoals datums met een herstelcallback, controleer de ontlede gegevens en converteer gegevens naar JSON en terug.
- Lees en schrijf het JSON-formaat
JavaScript-objecten en JSON: uitleg
1Modelleer gegevens met objecten
Een object bewaart samenhangende waarden bij elkaar onder namen, zodat een record één boek, persoon of meting kan beschrijven. Met die namen kun je één veld wijzigen, een heel record bekijken en lijsten van records ordenen. Je volgt ook welke variabelen naar hetzelfde object verwijzen. Dat onderscheid is van belang wanneer een wijziging op twee plaatsen verschijnt, een kopie geneste gegevens bevat of een ontbrekend veld een zinvolle standaardwaarde nodig heeft.
1.1 Maak objecten en werk met hun eigenschappen
Een object groepeert samenhangende waarden onder namen. Elke eigenschap koppelt een sleutel aan een waarde. Gebruik één object voor een record en een array van objecten voor een geordende lijst. Parallelle arrays kunnen hun onderlinge samenhang verliezen als er maar één wordt gesorteerd of gewijzigd.
Maak en lees een record
const book = { title: "Dune", pages: 412, available: true };
book.title; // "Dune"
book["title"]; // "Dune"
Eigenschapswaarden kunnen behalve primitieve waarden ook arrays, objecten of functies zijn. Sleutels zijn strings of symbolen; deze voorbeelden gebruiken strings. Stringsleutels die geldige identifiers zijn, hebben geen aanhalingstekens nodig. Sleutels met spaties of koppeltekens hebben die wel nodig: { "release-year": 1965 }. Numerieke sleutels worden strings, dus { 1: "a" } heeft de sleutel "1". Objectliterals staan een komma aan het einde toe.
Puntnotatie gebruikt de letterlijke naam na de punt. Blokhaaknotatie evalueert een expressie:
const field = "pages";
book[field]; // 412
book.field; // undefined
De tweede expressie zoekt naar een eigenschap met de naam "field". Blokhaken zijn ook geschikt voor book["release-year"]. Een ontbrekende eigenschap geeft undefined terug; als je via die waarde verder leest, zoals in book.author.name, wordt een TypeError opgeworpen als author ontbreekt.
Wijzig de inhoud van het object
book.author = "Frank Herbert";
book.pages = 896;
delete book.available;
Een toewijzing voegt een ontbrekende eigenschap toe of vervangt een bestaande waarde. Verwijderen haalt de eigenschap zelf weg, dus "available" in book is nu onwaar. const houdt de variabele gekoppeld aan dit object, maar staat wijzigingen in de inhoud toe.
Voor const reading = { city: "Nairobi", tempC: 24.5 }; slaat reading.tempC += 1.5; de waarde 26 op. Daarna voegt reading.humidity = 61; een veld toe. Met const key = "humidity"; leest reading[key] de waarde 61. Een naam zoals tempC maakt de eenheid van de meting zichtbaar.
Gebruik variabelen in een literal
const name = "Lena";
const age = 29;
const person = { name, age };
const lang = "nl";
const greeting = { [lang]: "Hallo" };
De verkorte eigenschapsnotatie { name, age } betekent hetzelfde als { name: name, age: age }. Bij een berekende eigenschapsnaam wordt de expressie tussen blokhaken geëvalueerd: greeting heeft de eigenschap "nl". Zonder die blokhaken zou { lang: "Hallo" } de letterlijke sleutel "lang" aanmaken.
Belangrijkste punten
- Een object groepeert samenhangende waarden in benoemde eigenschappen.
- Gebruik blokhaken voor een sleutel die in een variabele is opgeslagen of een koppelteken bevat.
- Een toewijzing voegt een eigenschap toe of vervangt die;
deleteverwijdert de eigenschap. constlegt de variabele vast, niet de inhoud van het object.- De verkorte eigenschapsnotatie neemt een variabelewaarde over; een berekende sleutel evalueert een expressie.
1.2 Controleer de eigenschappen van een object en doorloop ze met een lus
Controleren of een veld bestaat is iets anders dan de waarde ervan controleren. Een lege string, nul of false kan een volkomen geldige opgeslagen waarde zijn.
Stel de juiste vraag over aanwezigheid
const item = { stock: 0, note: undefined };
Object.hasOwn(item, "stock"); // true
"note" in item; // true
Boolean(item.stock); // false
Object.hasOwn(obj, key) controleert alleen de eigen eigenschappen van het object. De operator in controleert ook overgeërfde eigenschappen: "toString" in {} is true, terwijl Object.hasOwn({}, "toString") gelijk is aan false. Oudere code roept vaak obj.hasOwnProperty(key) aan.
Een voorwaarde zoals if (item.stock) controleert of de waarde truthy is. Ze kan geen onderscheid maken tussen een ontbrekend veld en een aanwezig veld met de waarde nul. Hetzelfde probleem geldt voor "", false, null, undefined en NaN. Zelfs een waarde undefined kan bij een bestaande eigenschap horen, zoals bij note hierboven.
Kies sleutels, waarden of paren
Voor const scores = { Ana: 82, Ben: 74, Chen: 91 }; geven deze functies arrays terug van eigen opsombare eigenschappen met strings als sleutels:
| Expressie | Resultaat |
|---|---|
Object.keys(scores) | ["Ana", "Ben", "Chen"] |
Object.values(scores) | [82, 74, 91] |
Object.entries(scores) | [["Ana", 82], ["Ben", 74], ["Chen", 91]] |
Het object heeft geen lengte zoals een array: scores.length is undefined. Object.keys(scores).length telt drie eigenschappen. Om de scores op te tellen, reduceer je de waarden met nul als beginwaarde. De som is 247 en het gemiddelde is ongeveer 82,33.
Doorloop met beide onderdelen beschikbaar
let bestName;
let bestScore = -Infinity;
for (const [name, score] of Object.entries(scores)) {
if (score > bestScore) {
bestName = name;
bestScore = score;
}
}
De lus vergelijkt achtereenvolgens 82, 74 en 91 met de hoogste score tot dan toe. De lus eindigt met "Chen" en 91. Het patroon met blokhaken geeft namen aan de twee onderdelen van elk paar.
Een gewoon object is niet itereerbaar, dus for...of scores werpt een TypeError op. Object.entries(scores) levert een itereerbare array. De oudere for...in-lus levert stringsleutels op en kan overgeërfde opsombare eigenschappen bevatten.
Zet sleutel-waardeparen weer om in een object
const weightsG = { flour: 500, sugar: 250, salt: 5 };
const weightsKg = Object.fromEntries(
Object.entries(weightsG).map(([item, g]) => [item, g / 1000])
);
entries levert paren op, map wijzigt elke waarde met behoud van de sleutel en fromEntries bouwt het record opnieuw op. Het resultaat is { flour: 0.5, sugar: 0.25, salt: 0.005 }; weightsG blijft ongewijzigd.
De volgorde van eigen eigenschappen ligt vast. Array-indexsleutels van "0" tot en met "4294967294" verschijnen eerst in oplopende volgorde; andere stringsleutels volgen de invoegvolgorde. Een voorloopnul, zoals in "01", voorkomt dat een sleutel een array-index is. Zo geeft Object.keys({ b: 1, 2: "x", a: 2, 1: "y" }) de array ["1", "2", "b", "a"]. Gebruik een array als posities betekenis hebben.
Belangrijkste punten
- Of een eigenschap bestaat en of haar waarde truthy is, zijn verschillende vragen.
Object.hasOwncontroleert eigen eigenschappen;incontroleert ook overgeërfde eigenschappen.Object.entrieslevert sleutel-waardeparen voor lussen en transformaties.Object.fromEntriesbouwt een object opnieuw op uit paren.- Array-indexsleutels komen in de eigenschapsvolgorde vóór andere stringsleutels.
- Tel eigen opsombare stringsleutels met
Object.keys(obj).length.
1.3 Begrijp referenties, kopiëren en vergelijken
Twee variabelen kunnen naar één object verwijzen. Voordat je een wijziging voorspelt, bepaal je of de code een nieuw object heeft gemaakt of een referentie naar een bestaand object heeft gekopieerd.
Volg identiteit los van gegevens
const p1 = { x: 1 };
const p2 = p1;
p2.x = 99;
p1.x; // 99
p1 === p2; // true
De toewijzing heeft de referentie gekopieerd. Beide namen bereiken dezelfde eigenschap. Toewijzing van primitieve waarden werkt anders: na let a = 5; let b = a; b = 6; blijft a gelijk aan 5.
Objecten worden zowel met === als met == op identiteit vergeleken. Twee literals maken afzonderlijke objecten aan, ook als alle velden overeenkomen: ({ x: 1 } === { x: 1 }) is false. Om hun gegevens te vergelijken, vergelijk je de relevante eigenschappen. Een overeenkomstige weergave is geen controle op identiteit.
Als je een object aan een functie doorgeeft, wordt de referentie ook gekopieerd. Een functie die order.status = "shipped"; uitvoert, wijzigt het object van de aanroeper. Als de functie in plaats daarvan { ...order, status: "shipped" } teruggeeft, maakt ze een nieuw record op het hoogste niveau aan.
Onderscheid const, bevriezen en kopiëren
const cart = { items: 2 }; staat cart.items = 3; toe, maar de hertoewijzing cart = {}; werpt een TypeError op. Object.freeze(cart) blokkeert wijzigingen in de eigen eigenschappen. In strikte modus werpen pogingen om die toe te voegen, te verwijderen of te overschrijven een TypeError op.
Bevriezen is oppervlakkig. Als een bevroren record een ander object bevat, kunnen de velden van dat geneste object nog steeds veranderen. Een bevroren container en een diepgaand onveranderlijke structuur zijn verschillende dingen.
Volg een oppervlakkige kopie
const settings = { theme: "dark", font: { size: 14 } };
const copy = { ...settings };
copy.theme = "light";
copy.font.size = 18;
Spreadsyntaxis maakt een nieuw buitenste object. De waarde van theme wordt gekopieerd, dus als je copy.theme wijzigt, blijft settings.theme gelijk aan "dark". De waarde van font is een referentie die naar beide records wordt gekopieerd. Als je copy.font.size bijwerkt, wordt settings.font.size daarom ook 18.
Object.assign({}, settings) maakt ook een oppervlakkige kopie. Een oppervlakkige kopie maakt een afzonderlijk buitenste record, terwijl de identiteit van geneste objecten en arrays behouden blijft.
Kopieer geneste gegevens wanneer ze onafhankelijk moeten zijn
const deep = structuredClone(settings);
deep.font.size = 22;
settings.font.size; // 18
structuredClone kopieert geneste objecten en arrays, samen met ondersteunde waarden zoals Map, Set en Date. De functie verwerkt ook circulaire referenties. De nieuwe geneste font kan onafhankelijk veranderen. Functies kunnen niet op deze manier worden gekloond: een object met een methode veroorzaakt een DataCloneError.
Een heen-en-terugconversie via JSON, JSON.parse(JSON.stringify(obj)), kopieert alleen gegevens die geschikt zijn voor JSON. Eigenschappen met undefined of functies vallen weg, datums worden strings en sleutel-waardeparen van Map en waarden van Set gaan verloren tenzij je ze converteert. Kies een kloon voor onafhankelijke, ondersteunde JavaScript-gegevens en kies JSON als je een tekstweergave wilt maken.
Belangrijkste punten
- Toewijzingen en functieaanroepen kopiëren objectreferenties.
- Objecten worden op identiteit vergeleken, ook als hun velden overeenkomen.
- Een oppervlakkige kopie deelt geneste objecten.
Object.freezeblokkeert wijzigingen in eigen eigenschappen, maar werkt oppervlakkig.structuredClonekopieert ondersteunde geneste gegevens en kan geen functies kopiëren.
1.4 Werk met geneste gegevens
Geneste gegevens combineren records en lijsten. Lees een pad stap voor stap en controleer of elke stap uitkomt bij een object, een array of een eindwaarde.
Lees en verwerk een lijst binnen een record
const order = {
id: 1042,
customer: { name: "Sara", city: "Lisbon" },
items: [
{ product: "Tea", qty: 2, unitPrice: 4.5 },
{ product: "Mug", qty: 1, unitPrice: 9 }
]
};
order.customer.city leest "Lisbon". order.items[1].product selecteert eerst de array met items, dan het tweede record daarvan en vervolgens "Mug". order.items.length is 2.
De arraymethoden die je al kent, werken met eigenschappen van records. map(item => item.product) levert productnamen op. filter(item => item.qty > 1) behoudt de regel met thee. find(item => item.product === "Mug") geeft het bestaande record van de mok terug, dus als je dat teruggegeven record wijzigt, verandert het item in de bestelling.
Om het totaal te berekenen, gebruik je order.items.reduce((sum, item) => sum + item.qty * item.unitPrice, 0). De eerste regel telt 9 erbij op; de tweede telt er nog eens 9 bij op, wat 18 oplevert. Door een totaal te berekenen wanneer het nodig is, voorkom je dat een afzonderlijk opgeslagen totaal veroudert als items veranderen.
Lees optionele gegevens met een terugvaloptie
order.shipping?.date; // undefined
order.customer?.city ?? "unknown"; // "Lisbon"
Optionele ketenvorming, ?., stopt wanneer de waarde direct links ervan null of undefined is. Een directe order.shipping.date zou een TypeError opwerpen. Controleer elke optionele schakel in een langer pad. Blokhaaknotatie en aanroepen ondersteunen dit ook: order.items?.[0] en order.print?.().
Optionele ketenvorming is bedoeld voor waarden die mogen ontbreken. Verplichte velden hebben nog steeds controles of fouten nodig die een onjuist record zichtbaar maken. Optionele ketenvorming kan niet links van een toewijzing staan: order.shipping?.date = "2026-05-01" is een syntaxisfout.
De operator ?? voor terugval bij null of undefined gebruikt de rechterkant alleen bij null of undefined. De operator behoudt nul, false en "". Bij const qty = 0; blijft qty ?? 1 nul, terwijl qty || 1 de waarde 1 wordt omdat || elke falsy-waarde vervangt.
Kies een bruikbare structuur
Een array van records is geschikt om gegevens weer te geven, te filteren en te ordenen. Een object met ID's als sleutels maakt rechtstreeks opzoeken mogelijk: usersById["u23"].name. Een Map is nuttig wanneer opzoeksleutels vaak worden toegevoegd en verwijderd.
Nieuwer JavaScript biedt Object.groupBy, dat sinds 2024 breed beschikbaar is:
const tasks = [
{ title: "Book flights", status: "done" },
{ title: "Pack", status: "todo" },
{ title: "Renew passport", status: "done" }
];
const grouped = Object.groupBy(tasks, task => task.status);
grouped.done bevat twee records en grouped.todo bevat er één. Het resultaat heeft geen prototype en dus geen overgeërfde methode toString. Een ouder alternatief bouwt de arrays voor deze statussleutels expliciet op:
const groupedOlder = tasks.reduce((groups, task) => {
if (!Object.hasOwn(groups, task.status)) {
groups[task.status] = [];
}
groups[task.status].push(task);
return groups;
}, {});
Het eerste record in elke groep maakt de bijbehorende array aan. Latere records worden aan diezelfde array toegevoegd. Deze accumulator is een gewoon object; het resultaat van de nieuwere methode heeft geen prototype. Gebruik consistente namen en waardetypen in alle records; namen zoals distanceKm en tempC houden ook eenheden zichtbaar.
Belangrijkste punten
- Lees een genest pad vanaf het buitenste object naar de benodigde waarde.
findgeeft het bestaande record terug, geen kopie.?.stopt bij een schakel met null of undefined;??biedt dan een terugvaloptie.- Gebruik een array voor een geordende lijst en gegevens met sleutels om rechtstreeks op te zoeken.
Object.groupBygroepeert records in arrays onder sleutels.- Consistente veldnamen, typen en eenheden maken records eenvoudiger te verwerken.
2Geef objecten gedrag met methoden en this
Met methoden kan een object zijn gegevens combineren met acties die die gegevens gebruiken. Het korte woord this verbindt een actie met een object, maar de waarde ervan hangt af van hoe de functie wordt uitgevoerd. Je volgt gewone methodeaanroepen, geleende methoden en callbacks en kiest vervolgens een omhullende functie of een gebonden functie wanneer een actie haar object moet behouden. De voorbeelden worden als modules uitgevoerd, dus geldt de strikte modus tenzij een voorbeeld expliciet niet-strikte code gebruikt.
2.1 Schrijf methoden die de gegevens van hun object gebruiken
Een methode is een eigenschap met een functie als waarde, die via een object wordt aangeroepen. Daarmee kan een actie de huidige gegevens van het record gebruiken.
Schrijf een methode met this
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
counter.increment(); // 1
counter.increment(); // 2
De verkorte notatie increment() { ... } definieert een eigenschap met een gewone functie als waarde. In counter.increment() wordt het ontvangende object counter de waarde van this. Elke aanroep leest de opgeslagen telling, telt er één bij op en geeft het nieuwe getal terug.
Een losse count selecteert een variabele, niet de eigenschap. Zonder bijbehorende variabele werpt count += 1 een ReferenceError op. Gebruik this.count om het veld van het ontvangende object te bereiken.
Lees een functie of voer die uit
counter.increment leest een waarde van het type "function". De haakjes in counter.increment() voeren de functie uit en geven de retourwaarde. Wanneer je een actie doorgeeft voor later gebruik, heeft de ontvangende code de functie nodig en niet het resultaat van een uitvoering op dat moment.
Ingebouwde methoden gebruiken deze aanroepvorm ook: Math.max(3, 7) geeft 7 terug en "abc".toUpperCase() geeft "ABC" terug.
Hergebruik een actie
function describe() {
return this.name + " (" + this.year + ")";
}
const film = { name: "Up", year: 2009, describe };
const song = { name: "Hello", year: 2015, describe };
film.describe() geeft "Up (2009)" terug; song.describe() geeft "Hello (2015)" terug. Met this kan dezelfde functie beide ontvangende objecten lezen. Als je film.name vast in de code zou schrijven, zou je de functie aan de variabele film binden.
Geef het ontvangende object terug voor een volgende actie
const playlist = {
tracks: [],
add(title) { this.tracks.push(title); return this; },
count() { return this.tracks.length; }
};
playlist.add("Rain").add("Waves").count(); // 2
Elke aanroep van add geeft de afspeellijst terug, zodat de volgende methode op dat object kan worden opgezocht. Als add een getal zou teruggeven, zou de keten breken omdat de volgende add op dat getal zou worden opgezocht.
Gewone JSON-conversie laat methoden weg: bij het omzetten van { name: "Kit", hi() { return 1; } } naar een string wordt alleen name geschreven. Ontleden kan weggelaten code niet herstellen. Records voor opslag of uitwisseling bevatten vaak gewone gegevens en gebruiken afzonderlijke verwerkingsfuncties.
Belangrijkste punten
- Een methode is een eigenschap met een functie als waarde, die via een object wordt aangeroepen.
- In
obj.method()gebruikt een gewone methodeobjalsthis. - Een functiewaarde en het resultaat van de aanroep ervan zijn verschillende waarden.
- Door
thisterug te geven, kan er nog een methodeaanroep volgen. - Gewone JSON-conversie laat eigenschappen met een functie als waarde weg.
2.2 Leg uit hoe this zijn waarde krijgt
Bij een gewone functie bepaalt de aanroep this. Een functie in een object opslaan verbindt die niet blijvend aan dat object.
Volg het ontvangende object bij de aanroep
const a = { n: "A", who() { return this.n; } };
const b = { n: "B" };
b.who = a.who;
a.who(); // "A"
b.who(); // "B"
Beide eigenschappen bevatten dezelfde functie. Het ontvangende object vóór de punt verschilt, dus verschillen de resultaten. De oorspronkelijke plaats van de functie bepaalt niet welk object de functie leest.
Bij een gewone aanroep, f(), levert de strikte modus undefined als this. JavaScript-modules worden altijd in strikte modus uitgevoerd; een script of functie kan ook beginnen met "use strict";. Een niet-strikte gewone functie die op deze manier wordt aangeroepen, gebruikt in plaats daarvan het globale object globalThis. In een browser is dat globale object window.
Herken de omringende context van een pijlfunctie
Een pijlfunctie heeft geen eigen this. Ze behoudt de this van de omringende code waar ze is gemaakt. Een objectliteral maakt geen nieuwe this-context aan.
// At the top level of a module:
const user = {
name: "Ida",
hi: () => "Hi, " + this.name
};
De aanroep user.hi() werpt een TypeError op: de pijlfunctie heeft de this van het hoogste niveau van de module vastgelegd, en die is undefined. Als je de aanroep op een methodeaanroep laat lijken, krijgt de pijlfunctie geen nieuw ontvangend object. Op het hoogste niveau van een klassiek script is de omringende this in plaats daarvan het globale object.
Gebruik een gewone methode wanneer de actie het aanroepende object nodig heeft. Gebruik een pijlfunctie binnen die methode wanneer een callback de context van de methode moet behouden:
const group = {
title: "Team",
members: ["Ana", "Ben"],
list() {
return this.members.map(m => this.title + ": " + m);
}
};
group.list(); // ["Team: Ana", "Team: Ben"]
list krijgt group via de methodeaanroep. De pijlfunctie wordt binnen die uitgevoerde methode gemaakt en behoudt dezelfde this. Een strikte gewone callback zonder opgegeven ontvangend object zou undefined ontvangen, zodat this.title daar zou mislukken.
Gebruik een beslisvolgorde
Als je een aanroep tegenkomt, bepaal dan eerst welke functie wordt aangeroepen:
- Een pijlfunctie behoudt de omringende
this;call,applyenbindkunnen die niet vervangen. - Een gebonden gewone functie behoudt de gebonden
this, ook bij gebruik vancallofapply. - Een ongebonden gewone functie die met
callofapplywordt aangeroepen, gebruikt de opgegeventhis. - Een gewone aanroep
obj.method()gebruiktobj. - Een gewone functieaanroep gebruikt
undefinedin strikte modus of het globale object in niet-strikte modus.
Callbacks kunnen een ontvangend object krijgen van de code die ze aanroept. Zo krijgt een gewone DOM-eventlistener die met addEventListener is geregistreerd, het element waarop die is geregistreerd als this. Bekijk hoe de ontvangende code een callback aanroept voordat je aanneemt dat het een gewone functieaanroep is.
Belangrijkste punten
- Een gewone functie krijgt
thisvia de aanroep, dus als je een methode leent, verandert het ontvangende object. - Een gewone functieaanroep in strikte modus gebruikt
undefinedalsthis. - Een pijlfunctie behoudt de omringende
thisvan de plaats waar ze is gemaakt. - Een gebonden ontvangend object heeft voorrang op een latere
callofapply. - Een pijlfunctie binnen een gewone methode kan de
thisvan die methode behouden.
2.3 Behoud de waarde van this wanneer je methoden als callbacks doorgeeft
Als je een methode uit haar object haalt, blijft de functie behouden, maar gaat de oorspronkelijke aanroepexpressie verloren. Een callback moet zo worden aangeroepen dat die het benodigde object krijgt.
Onderzoek een losgekoppelde methode
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
const inc = counter.increment;
inc(); // TypeError in strict mode
inc() is een gewone functieaanroep, dus is this gelijk aan undefined. Het lezen van this.count mislukt voordat de telling kan worden verhoogd. In niet-strikte code gebruikt een gewone aanroep het globale object en kan die in plaats daarvan een globale count beschrijven; de aanroep bereikt de teller niet.
Hetzelfde probleem doet zich voor bij arraycallbacks. [1, 2].map(counter.increment) geeft een functie aan map zonder het oorspronkelijke ontvangende object. De arraywaarden die als argumenten worden doorgegeven, leveren geen this.
Omhul de methodeaanroep
const results = [1, 2].map(() => counter.increment());
// results is [1, 2]; counter.count is 2
De callback is een pijlfunctie die een gewone aanroep counter.increment() uitvoert. Die aanroep heeft een ontvangend object. De omhullende functie negeert bewust de waarden die map doorgeeft; elke aanroep verhoogt de teller één keer. Deze vorm is handig wanneer de callback maar op één plaats nodig is.
Bind een herbruikbare functie
Begin met een nieuwe teller op nul:
const boundInc = counter.increment.bind(counter);
const results = [1, 2].map(boundInc);
// results is [1, 2]; counter.count is 2
bind geeft een nieuwe functie terug; de methode wordt nog niet aangeroepen. De nieuwe functie behoudt counter als ontvangend object. Als je de functie opnieuw aan een ander object bindt, kun je dat ontvangende object niet vervangen. Elke aanroep van bind maakt een afzonderlijke functie, dus bewaar het resultaat wanneer code later precies dezelfde callback moet herkennen.
Binden kan ook vooraanstaande argumenten vastleggen. Met function multiply(a, b) { return a * b; } gevolgd door const double = multiply.bind(null, 2); geeft double(21) de waarde 42 terug. null vult de positie voor het ontvangende object omdat deze functie geen this gebruikt; 2 vult de eerste gewone parameter.
Voer één keer uit met call of apply
function describe(unit) {
return this.value + " " + unit;
}
describe.call({ value: 12 }, "kg"); // "12 kg"
describe.apply({ value: 12 }, ["kg"]); // "12 kg"
Beide vormen worden direct uitgevoerd met het gekozen ontvangende object. call geeft argumenten afzonderlijk door; apply geeft ze door in een array. De context van een pijlfunctie ligt vast door de omgeving, dus kunnen deze methoden de this van een pijlfunctie niet vervangen.
Als je counter.increment() als callback doorgeeft, wordt de methode direct uitgevoerd en het teruggegeven getal doorgegeven. Dat is niet de functie die map nodig heeft. Bij een eventregistratie zoals button.addEventListener("click", counter.increment()) verandert de teller direct en veroorzaakt de numerieke listener een TypeError. Geef een functiewaarde, een omhullende pijlfunctie of een opgeslagen gebonden functie door.
Belangrijkste punten
- Als je een methode loskoppelt, verliest die haar oorspronkelijke ontvangende object.
- Een omhullende pijlfunctie kan de benodigde methodeaanroep later uitvoeren.
bindmaakt een functie met een vast ontvangend object en optionele vooraanstaande argumenten.callenapplyworden direct uitgevoerd; de vorm van hun argumenten verschilt.- Argumenten die als callback dienen, moeten functies zijn en niet het numerieke resultaat van een methodeaanroep.
3Pak gegevens uit en combineer ze met destructurering, spreadsyntaxis en restsyntaxis
Met destructurering geef je namen aan geselecteerde onderdelen van een object of een geordende verzameling. Met spreadsyntaxis bouw je waarden op uit bestaande onderdelen, terwijl restsyntaxis de overgebleven onderdelen verzamelt. Deze vormen komen vaak samen voor in functies die opties ontvangen of bijgewerkte records teruggeven. Door goed naar hun positie te kijken, kun je voorspellen welke variabelen bestaan, welke standaardwaarden gelden en of geneste gegevens met het origineel worden gedeeld.
3.1 Destructureer objecten
Met objectdestructurering lees je benoemde velden in lokale variabelen. Je selecteert waarden zonder het hele bronrecord te kopiëren.
Koppel en hernoem
const book = { title: "Dune", pages: 412 };
const { pages, title: bookTitle, rating: stars = 0 } = book;
De koppeling gebruikt eigenschapsnamen, niet hun volgorde. Hiermee wordt pages gedeclareerd met de waarde 412, bookTitle met "Dune" en stars met 0. Er wordt geen variabele title of rating gedeclareerd: de naam na een dubbele punt is de lokale doelvariabele.
Een ontbrekend veld levert undefined op. Een standaardwaarde vervangt alleen undefined en behoudt null, nul, false en lege strings. const { a = 5 } = { a: null }; laat a daarom op null staan.
Volg geneste velden
const data = {
location: { name: "Oslo" },
current: { tempC: -3, windKph: 18 }
};
const {
location: { name },
current: { tempC, windKph: wind }
} = data;
De gedeclareerde variabelen zijn name, tempC en wind, met de waarden "Oslo", -3 en 18. De omhullende namen location en current selecteren paden; ze worden niet ook variabelen.
Als een buitenste object ontbreekt, mislukt het lezen van een geneste waarde. const { shipping: { date } } = {}; werpt een TypeError op. Geef een standaardwaarde voor het buitenste niveau als dat veld undefined kan zijn:
const { shipping: { date } = {} } = {};
// date is undefined
Dit vervangt shipping niet als de waarde null is. Als je null of undefined rechtstreeks destructureert, wordt ook een fout opgeworpen, dus moet de bron bruikbaar zijn voordat het uitpakken begint.
Ontvang benoemde opties
function formatUser({ name, age = "unknown" }) {
return name + ", " + age;
}
formatUser({ name: "Mo" }) geeft "Mo, unknown" terug. Als je de velden herschikt zoals in { age: 40, name: "Ines" }, krijg je nog steeds "Ines, 40" terug. Een aanroep van formatUser zonder argument mislukt omdat er geen object is om uit te pakken. Een standaardwaarde voor de hele parameter maakt die aanroep mogelijk:
function greet({ name = "guest" } = {}) {
return "Hi, " + name;
}
greet(); // "Hi, guest"
De buitenste standaardwaarde vangt een weggelaten argument op; de binnenste vangt een ontbrekende naam op. Als je null doorgeeft, mislukt het nog steeds. Om waarden aan bestaande variabelen toe te wijzen, zet je een instructie met een objectpatroon tussen haakjes: let x, y; ({ x, y } = { x: 4, y: 7 });. Anders worden de eerste accolades gelezen als een instructieblok.
Belangrijkste punten
- Objectpatronen koppelen eigenschappen op naam.
- Een dubbele punt hernoemt de variabele; de bronsleutel verandert niet.
- Standaardwaarden vervangen
undefined, ook bij ontbrekende eigenschappen, en behoudennull. - Geneste patronen hebben op elk niveau een bruikbaar object nodig.
- Een standaardwaarde voor de hele parameter en een standaardwaarde voor een eigenschap vangen verschillende ontbrekende waarden op.
- Met haakjes kan een objectpatroon waarden toewijzen aan bestaande variabelen.
3.2 Destructureer arrays en andere itereerbare waarden
Arraydestructurering leest waarden op positie uit een itereerbare waarde. Komma's bepalen welke waarden worden geselecteerd; de variabelenamen kiezen de posities niet.
Selecteer of sla posities over
const medals = ["gold", "silver", "bronze"];
const [first, second] = medals;
const [, , third] = medals;
De variabelen krijgen "gold", "silver" en "bronze". Lege plaatsen nemen waarden in zonder variabelen te declareren. Een naam voorbij de beschikbare waarden krijgt undefined. Standaardwaarden vervangen alleen undefined:
const [p, q = 10] = [1]; // p is 1; q is 10
const [r = 10] = [null]; // r is null
Verzamel de overige waarden
const [head, ...tail] = [1, 2, 3, 4];
// head is 1; tail is [2, 3, 4]
Het laatste rest-element maakt een nieuwe array, die leeg is als er niets overblijft. Het moet als laatste staan. Eventuele objectwaarden in die array behouden hun identiteit; ze worden door het verzamelen niet diep gekloond.
Lees een teruggegeven paar of verwissel variabelen
function minMax(nums) {
return [Math.min(...nums), Math.max(...nums)];
}
const [lo, hi] = minMax([4, 9, 1]);
// lo is 1; hi is 9
De aanroeper volgt de volgorde die de functie bij het teruggeven gebruikt. Bij veel resultaatvelden voorkomen benoemde objecteigenschappen dat je posities moet onthouden.
Met let x = 1, y = 2; verwisselt [x, y] = [y, x]; de variabelen. De array aan de rechterkant wordt vóór beide toewijzingen geëvalueerd als [2, 1], zodat beide oude waarden behouden blijven zonder tijdelijke variabele.
Pak andere itereerbare waarden uit
Strings en Sets kun je ook uitpakken: const [initial] = "Zoe"; geeft "Z". Sets leveren waarden in invoegvolgorde. Items van een Map zijn geordende paren:
const distances = new Map([["park", 2], ["lake", 5]]);
for (const [place, distanceKm] of distances) {
console.log(place, distanceKm);
}
De lus ontvangt een paar, waarna het patroon de sleutel en waarde scheidt. Object.entries levert dezelfde paarstructuur.
Een gewoon object is niet itereerbaar, dus werpt const [name] = { name: "Ana" }; een TypeError op. Gebruik accolades om het benoemde veld te selecteren: const { name } = { name: "Ana" };. Blokhaken vereisen een reeks waarden; accolades selecteren eigenschappen op naam.
Belangrijkste punten
- Arraypatronen koppelen op positie en lege plaatsen slaan waarden over.
- Een ontbrekende positie wordt
undefined, tenzij een standaardwaarde die vervangt. - Een rest-element aan het einde verzamelt de overige waarden in een nieuwe array.
- Arraypatronen werken ook op strings, Sets en sleutel-waardeparen van Maps.
3.3 Kopieer, voeg samen en verzamel met spreadsyntaxis en restsyntaxis
De drie punten, ..., hebben twee verwante taken. Spreadsyntaxis vouwt bestaande gegevens uit in een waarde of aanroep. Restsyntaxis verzamelt waarden in een variabele waar een patroon of parameter die declareert.
Voeg samen in volgorde van prioriteit
const defaults = { lang: "en", units: "metric", alerts: true };
const user = { lang: "pt", alerts: false };
const options = { ...defaults, ...user };
// { lang: "pt", units: "metric", alerts: false }
Spreadsyntaxis voor objecten kopieert eigen opsombare eigenschappen. Als een sleutel opnieuw voorkomt, krijgt de latere waarde voorrang. Als je user vóór defaults plaatst, worden de instellingen van de gebruiker overschreven. Als je null of undefined met spreadsyntaxis in een object opneemt, wordt niets toegevoegd.
Kopieën met spreadsyntaxis zijn oppervlakkig. Als een genest record verandert, kopieer dan ook dat niveau:
const settings = { theme: "dark", font: { size: 14, family: "serif" } };
const next = {
...settings,
font: { ...settings.font, size: 18 }
};
De buitenste spreadsyntaxis behoudt theme. De binnenste behoudt family en vervangt size. settings.font.size blijft 14 omdat het gewijzigde geneste record nieuw is.
Vervang één record in een lijst
const todos = [{ id: 1, done: false }, { id: 2, done: false }];
const updated = todos.map(t =>
t.id === 2 ? { ...t, done: true } : t
);
map maakt een nieuwe array. Het overeenkomende item wordt een nieuw object, dus is updated[1].done waar terwijl todos[1].done onwaar blijft. Het ongewijzigde eerste item wordt opnieuw gebruikt: updated[0] === todos[0] is waar. Voor onafhankelijke bijwerkingen hoef je ongewijzigde records niet te kopiëren.
Vouw itereerbare waarden uit
In een arrayliteral of functieaanroep haalt spreadsyntaxis waarden uit een itereerbare waarde. [...a, ...b] voegt de waarden samen in een nieuwe array. Math.max(...[4, 9, 1]) geeft drie argumenten door en geeft 9 terug. Een gewoon object kan niet in een array worden uitgevouwen: [...{ a: 1 }] werpt een TypeError op. Spreadsyntaxis voor objecten en voor itereerbare waarden gebruikt verschillende regels voor wat wordt gelezen.
Verzamel argumenten of resterende eigenschappen
function total(...nums) {
return nums.reduce((sum, n) => sum + n, 0);
}
total(2, 3, 5); // 10
total(); // 0
Een restparameter ontvangt een echte array, ook als die geen waarden ontvangt. De restparameter moet de laatste parameter zijn en er kan er maar één zijn. Het oudere arguments-object is geen echte array. Pijlfuncties hebben geen eigen arguments, maar kunnen wel de binding van een omringende gewone functie lezen.
Restsyntaxis voor objecten verzamelt eigen opsombare eigenschappen die nog niet zijn geselecteerd:
const userRecord = { id: 8, name: "Rae", password: "x9!k" };
const { password, ...publicUser } = userRecord;
// publicUser is { id: 8, name: "Rae" }
Dit maakt een nieuw record en laat de bron ongewijzigd. De rest-eigenschap moet als laatste staan. Kijk naar de plaats om de taken te onderscheiden: drie punten in een literal of aanroep vouwen waarden uit; drie punten in een parameterlijst of destructureringsdoel verzamelen waarden.
Belangrijkste punten
- Bij overlappende eigenschappen in spreadsyntaxis voor objecten krijgt de latere eigenschap voorrang.
- Kopieer elk genest niveau dat onafhankelijk moet veranderen.
- Spreadsyntaxis in arrays en aanroepen heeft een itereerbare waarde nodig.
- Restsyntaxis verzamelt resterende argumenten, items of eigenschappen en moet als laatste staan.
- Een bijwerking met map kan een gewijzigd record kopiëren en ongewijzigde records opnieuw gebruiken.
- Restparameters zijn echte arrays; het oudere
arguments-object is dat niet.
4Sla verzamelingen op met Map en Set
Sommige verzamelingen hebben sleutels nodig die objecten of getallen zijn, en andere moeten elke waarde maar één keer bewaren. Map en Set drukken die behoeften rechtstreeks uit. Je maakt sleutel-waardeparen, controleert de aanwezigheid, volgt de invoegvolgorde en zet verzamelingen om in arrays of objecten wanneer een andere bewerking die structuur nodig heeft. Gelijkheid blijft van belang: twee records met overeenkomende velden kunnen in beide verzamelingen twee afzonderlijke waarden blijven.
4.1 Sla sleutel-waardeparen op in een Map
Een Map slaat koppelingen tussen sleutels en waarden op. Anders dan de stringsleutels van een gewoon object kan een sleutel in een Map een getal, een object of een andere waarde zijn zonder in een string te worden omgezet.
Maak en beheer sleutel-waardeparen
const stock = new Map();
stock.set("apples", 12).set("pears", 7);
stock.get("apples"); // 12
stock.has("kiwis"); // false
stock.size; // 2
set voegt een sleutel-waardepaar toe of vervangt de waarde ervan en geeft de Map terug om aanroepen aaneen te schakelen. get geeft undefined terug voor een ontbrekende sleutel; gebruik has om dat te onderscheiden van een sleutel-waardepaar waarin undefined is opgeslagen. delete(key) geeft terug of een sleutel-waardepaar is verwijderd en clear() maakt de verzameling leeg.
Blokhaaknotatie gebruikt een andere opslagplaats: stock["plums"] = 5; voegt een gewone eigenschap toe aan het Map-object. Er wordt geen sleutel-waardepaar aangemaakt dat zichtbaar is voor get, has of size. Gebruik de Map-methoden voor sleutel-waardeparen.
Behoud sleuteltypen en identiteit
m.set(1, "number"); m.set("1", "text"); maakt twee sleutel-waardeparen aan. In een gewoon object zouden de sleutels 1 en "1" naar één eigenschap verwijzen. Map-sleutels worden vergeleken zoals met ===, behalve dat NaN gelijk is aan zichzelf en positieve en negatieve nul dezelfde sleutel delen.
const person = { id: 1 };
const notes = new Map([[person, "ready"]]);
notes.get(person); // "ready"
notes.get({ id: 1 }); // undefined
Bij de tweede opzoekactie wordt een nieuw object gemaakt. Overeenkomende velden maken dat niet tot dezelfde sleutel. Bewaar en hergebruik de oorspronkelijke objectreferentie wanneer je een object als sleutel gebruikt.
Doorloop en converteer paren
for (const [name, count] of stock) {
console.log(name, count);
}
Een Map levert [key, value]-paren in de volgorde waarin de sleutels voor het eerst zijn toegevoegd. Als je een waarde vervangt, verplaatst de sleutel niet. keys(), values() en entries() geven itereerbare weergaven terug die je met een lus kunt doorlopen of met spreadsyntaxis in arrays kunt opnemen. forEach geeft aan zijn callback eerst de waarde en dan de sleutel door.
new Map(Object.entries(obj)) zet de sleutel-waardeparen van een record om in een Map. Object.fromEntries(map) maakt een object; gebruik dit wanneer sleutels strings zijn, omdat objectsleutels niet elk type Map-sleutel kunnen behouden. [...map] maakt een array van paren, handig om de sleutel-waardeparen van een Map als JSON op te slaan.
Tel wisselende sleutels
const words = "the cat saw the dog and the bird".split(" ");
const counts = new Map();
for (const word of words) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
De eerste keer begint de telling bij nul en wordt er één opgeteld. Bij latere voorkomens wordt de opgeslagen telling gelezen en verhoogd. counts.get("the") is 3 en counts.size is 6: de grootte telt verschillende woorden, niet alle acht voorkomens.
Kies een gewoon object voor een record met bekende velden, vooral voor gegevens die geschikt zijn voor JSON. Kies een Map voor wisselende sleutels, frequente controles van de grootte of sleutels waarvan het type behouden moet blijven. De nieuwere methode Map.groupBy behoudt de typen groepssleutels:
const owner = { name: "Ari" };
const jobs = [{ owner, done: false }, { owner, done: true }];
const byOwner = Map.groupBy(jobs, job => job.owner);
byOwner.get(owner).length; // 2
Doorloop in oudere code de taken. Gebruik voor elke eigenaar has en set om eenmaal een groepsarray te maken en voeg daarna het record toe met get(owner).push(job). Door de eigenaar als objectsleutel te bewaren, onderscheid je verschillende eigenaars, ook als hun naamvelden overeenkomen. Een WeakMap kan metagegevens aan objecten koppelen zonder sleutelobjecten die verder onbereikbaar zijn in leven te houden. Een WeakMap heeft geen iteratie of grootte. Moderne WeakMaps accepteren ook niet-geregistreerde symbolen als sleutels.
Belangrijkste punten
- Map-sleutels behouden hun type en vergelijken objecten op identiteit.
- Gebruik
set,get,hasendeletevoor sleutel-waardeparen, geen blokhaaknotatie. sizetelt sleutel-waardeparen en iteratie volgt de invoegvolgorde van sleutels.- Maps worden geconverteerd via sleutel-waardeparen.
- Een WeakMap kan metagegevens van objecten bewaren zonder sleutelobjecten in leven te houden.
Map.groupBybehoudt de typen groepssleutels in een nieuwere groeperings-API.
4.2 Bewaar unieke waarden in een Set
Een Set slaat unieke waarden op. De belangrijkste vragen zijn of een waarde aanwezig is en hoe twee verzamelingen overlappen.
Voeg waarden toe en controleer ze
const tags = new Set(["js", "css", "js"]);
tags.size; // 2
tags.add("html");
tags.has("css"); // true
Een bestaande waarde toevoegen verandert niets. add geeft de Set terug om aanroepen aaneen te schakelen. delete(value) geeft terug of de waarde is verwijderd, terwijl clear() alle waarden verwijdert. De constructor ontvangt één itereerbare waarde: gebruik new Set([1, 2, 3]). new Set(1, 2, 3) werpt een TypeError op omdat de eerste invoer niet itereerbaar is. Een string is itereerbaar, dus bevat new Set("hello") de waarden "h", "e", "l" en "o".
Een Set heeft geen posities met indexen. tags[0] is undefined. Doorloop de Set met for...of, roep forEach aan of converteer naar een array voor bewerkingen zoals map en filter. Iteratie volgt de invoegvolgorde; als je een waarde verwijdert en opnieuw toevoegt, komt die achteraan te staan.
Verwijder dubbele waarden zonder te sorteren
const unique = [...new Set([3, 1, 3, 2, 1])];
// [3, 1, 2]
De Set behoudt het eerste voorkomen van elke waarde. Met spreadsyntaxis komen die waarden in een array terecht. Array.from(set) voert dezelfde conversie uit.
Waarden worden vergeleken zoals met ===, behalve dat NaN gelijk is aan zichzelf; positieve en negatieve nul tellen als één waarde. Objectwaarden worden op identiteit vergeleken: new Set([{ id: 1 }, { id: 1 }]).size is 2. Om één record per ID te bewaren, bouw je een Map met die ID als sleutel en lees je vervolgens de waarden. Latere records met dezelfde ID vervangen eerdere records, omdat set een bestaand sleutel-waardepaar bijwerkt.
Voor herhaalde aanwezigheidscontroles in grote verzamelingen voorkomt een Set dat includes een array één voor één moet doorzoeken. Gebruik een Set wanneer aanwezigheid belangrijker is dan positie.
Vergelijk twee verzamelingen
Nieuwere Set-methoden zijn vanaf 2024 beschikbaar in de grote browsers. Met a met de waarden 1, 2, 3, 4 en b met de waarden 3, 4, 5:
| Bewerking | Betekenis | Resulterende waarden |
|---|---|---|
a.union(b) | In minstens één verzameling | 1, 2, 3, 4, 5 |
a.intersection(b) | In beide | 3, 4 |
a.difference(b) | In a maar niet in b | 1, 2 |
a.symmetricDifference(b) | In precies één | 1, 2, 5 |
Deze methoden geven nieuwe Sets terug. isSubsetOf controleert of elke waarde in de andere verzameling zit. isSupersetOf controleert de omgekeerde insluiting. isDisjointFrom controleert of de verzamelingen geen waarden delen. Alle drie geven booleaanse waarden terug. Zo is new Set([3, 4]).isSubsetOf(a) waar. Verschil heeft een richting: waarden in b maar niet in a zouden alleen 5 zijn.
In een oudere omgeving kun je een doorsnede schrijven als new Set([...a].filter(x => b.has(x))).
Het gewone JSON.stringify(set) levert "{}" op, waarbij de opgeslagen waarden verloren gaan. Converteer naar een array voordat je JSON schrijft en gebruik vervolgens new Set(parsedArray) bij het lezen. Een WeakSet kan objecten als verwerkt markeren zonder verder onbereikbare objecten in leven te houden. Een WeakSet kan niet worden doorlopen. Moderne WeakSets accepteren ook niet-geregistreerde symbolen.
Belangrijkste punten
- Een Set bewaart elke verschillende waarde één keer en controleert aanwezigheid met
has. - Converteer een Set naar een array om indexen of arraymethoden te gebruiken.
- Objectwaarden blijven verschillend tenzij hun referenties overeenkomen.
- Vereniging, doorsnede, verschil en symmetrisch verschil beantwoorden verschillende vragen over aanwezigheid.
- Het verschil hangt af van welke Set eerst komt.
- Converteer Set-waarden naar een array voordat je JSON schrijft.
- Een WeakSet kan objecten markeren zonder ze in leven te houden.
5Converteer gegevens naar JSON en terug
JSON draagt gestructureerde gegevens over als tekst. Converteren tussen die tekst en actieve JavaScript-waarden is alleen nuttig als je weet welke informatie de conversie overleeft. Je herkent geldige JSON, bepaalt hoe waarden worden geschreven en handelt ongeldige invoer af bij het lezen. Na succesvol ontleden is ook een structuurcontrole nodig voordat het programma op de velden vertrouwt; geldige tekst alleen garandeert niet dat de gegevens aan de verwachtingen voldoen.
5.1 Lees en schrijf het JSON-formaat
JSON, een afkorting van JavaScript Object Notation, is een taalonafhankelijk tekstformaat voor gestructureerde gegevens. Een object is een actieve JavaScript-waarde; JSON is tekst die zo'n waarde kan beschrijven.
Herken de zes soorten waarden
JSON ondersteunt objecten, arrays, strings, getallen, booleaanse waarden en null. Elk daarvan kan de waarde op het hoogste niveau zijn. De tekst 42 is geldige JSON, ook zonder accolades. JSON heeft geen weergave voor functies, undefined, datums als afzonderlijk type, Map, Set, NaN of Infinity.
{
"name": "Amara",
"age": 34,
"languages": ["en", "yo"],
"address": null,
"member": true
}
Dezelfde structurele ideeën komen voor in JavaScript-literals, maar de toegestane schrijfwijze is strikter. JSON wordt gebruikt in configuraties en voor gegevensuitwisseling. Uitgewisselde JSON gebruikt UTF-8-codering en het mediatype application/json; JSON-bestanden gebruiken de extensie .json.
Pas de syntaxisregels toe
Elke objectsleutel moet een string tussen dubbele aanhalingstekens zijn. Strings vereisen ook dubbele aanhalingstekens. Komma's scheiden eigenschappen of arrayitems, maar na het laatste item mag geen komma staan. Commentaar is verboden. Witruimte tussen waarden en leestekens is toegestaan.
| Tekst | Waarom die ongeldig is |
|---|---|
{name: "Amara"} | De sleutel mist dubbele aanhalingstekens. |
{'name': 'Amara'} | Enkele aanhalingstekens begrenzen geen JSON-strings. |
{"a": 1,} | Na de laatste komma volgt geen eigenschap. |
{"a": undefined} | Undefined is geen JSON-waarde. |
Getallen gebruiken decimale notatie. 1.5e3, -0.25 en 0 zijn geldig. 07, +1 en 0x1F zijn ongeldig omdat JSON voorloopnullen, een plusteken aan het begin en hexadecimale notatie verbiedt.
Gebruik escapesequenties voor tekens in strings
Gebruik \" voor een dubbel aanhalingsteken, \\ voor een backslash, \n voor een nieuwe regel en \t voor een tab binnen een JSON-string. Een letterlijk regeleinde mag niet binnen een JSON-string voorkomen. Laat JSON.stringify escapesequenties genereren uit werkelijke stringwaarden, zodat aanhalingstekens in de tekst de uitvoer niet ongeldig kunnen maken.
Een Unicode-escapesequentie bestaat uit een backslash, de letter u en vier hexadecimale cijfers voor één UTF-16-code-eenheid. Zo staat \u00e9 voor é. Een teken buiten dat bereik kan twee van zulke escapesequenties nodig hebben; het kan ook rechtstreeks in de string worden geschreven. De aanhalingstekens rond JSON-tekst in JavaScript-broncode vormen een afzonderlijke laag ten opzichte van de aanhalingstekens binnen de JSON zelf.
Behoud identifiers en voorkom dubbele sleutels
JavaScript-getallen behouden elk geheel getal in het veilige bereik van -9.007.199.254.740.991 tot en met 9.007.199.254.740.991. Buiten dat bereik blijven sommige gehele getallen exact en worden andere afgerond. Het ontleden van '{"id":9007199254740993}' geeft een id-waarde van 9007199254740992. Sla lange identifiers op als JSON-strings wanneer de exacte cijfers van belang zijn.
Objectsleutels moeten binnen elk JSON-object uniek zijn. De JavaScript-functie JSON.parse bewaart het laatste voorkomen als een sleutel wordt herhaald: het ontleden van '{"a":1,"a":2}' levert { a: 2 } op. Afzonderlijke eigenschappen zijn niet uit die herhaalde naam te herstellen.
Belangrijkste punten
- JSON is tekst met zes soorten waarden, waaronder primitieve waarden op het hoogste niveau.
- Sleutels en strings hebben dubbele aanhalingstekens nodig; commentaar en komma's aan het einde zijn ongeldig.
- JSON-getallen staan geen hexadecimale notatie, plustekens aan het begin of voorloopnullen toe.
- Escapesequenties geven speciale tekens binnen strings weer.
- Gebruik strings voor lange identifiers waarvan de exacte cijfers behouden moeten blijven.
- Herhaalde objectsleutels zijn onveilig;
JSON.parsebewaart de laatste waarde.
5.2 Zet waarden om in JSON-tekst met JSON.stringify
JSON.stringify converteert ondersteunde JavaScript-waarden naar JSON-tekst. Bepaal wat de tekst moet behouden voordat je een record met methoden of verzamelingswaarden converteert.
Schrijf compacte of ingesprongen tekst
const person = { name: "Amara", age: 34, tags: ["admin"] };
const text = JSON.stringify(person);
// '{"name":"Amara","age":34,"tags":["admin"]}'
Het resultaat is een string, dus is typeof text gelijk aan "string". Eigen opsombare eigenschappen met strings als sleutels worden geschreven in de volgorde van Object.keys. JSON.stringify(person, null, 2) voegt regeleinden en twee spaties inspringing per niveau toe. Het tweede argument is null omdat er geen vervangingsargument wordt gebruikt. Numerieke inspringing is begrensd op 10 spaties; van een string voor inspringing worden hoogstens de eerste 10 tekens gebruikt.
Voorspel welke waarden wegvallen en veranderen
const data = {
a: undefined,
b: () => 1,
c: NaN,
d: [undefined, Infinity]
};
JSON.stringify(data); // '{"c":null,"d":[null,null]}'
Een objecteigenschap met undefined, een functie of een symbool wordt weggelaten. In een array wordt zo'n waarde null, zodat die positie behouden blijft. NaN en Infinity worden op beide plaatsen null. Op het hoogste niveau zorgen niet-ondersteunde waarden zoals undefined of een functie ervoor dat stringify de waarde undefined teruggeeft, geen JSON-tekst.
Een Date schrijft via toJSON zijn ISO-string in UTC. Gewone items van Map en Set worden niet geschreven, dus wordt elk van beide verzamelingen {}. Converteer Set-waarden naar een array en Map-items naar paren of een object met stringsleutels voordat je ze schrijft.
Een circulaire referentie en een gewone BigInt zoals 10n veroorzaken een TypeError. Gedeelde referenties die geen cyclus vormen, kunnen worden geserialiseerd, maar JSON behoudt hun gedeelde identiteit niet.
Kies gegevens met een vervangingsargument
const user = { name: "Rae", email: "rae@example.com", password: "x9!k", age: 31 };
JSON.stringify(user, ["name", "email"]);
// '{"name":"Rae","email":"rae@example.com"}'
Een array als vervangingsargument selecteert eigenschapsnamen. Een functie als vervangingsargument transformeert waarden wanneer ze worden bezocht, te beginnen met de hele invoer onder de sleutel "":
JSON.stringify(user, (key, value) =>
key === "password" ? undefined : value
);
Als de functie undefined teruggeeft, wordt een objecteigenschap weggelaten, wordt een arraypositie null of is het totale resultaat undefined wanneer de functie dit voor de hoofdwaarde teruggeeft. Geef voor gegevens die je wilt behouden de ongewijzigde waarde terug.
De methode toJSON() van een object kan de weergave ervan kiezen. Voor { celsius: 21, toJSON() { return { c: this.celsius }; } } schrijft omzetting naar een string '{"c":21}'.
Bouw JSON niet zelf op door strings tussen aanhalingstekens samen te voegen: aanhalingstekens of regeleinden in de inhoud kunnen de syntaxis ongeldig maken. Zet ook niet al geserialiseerde tekst om in een string met de verwachting een objectweergave te krijgen. Als je '{"a":1}' omzet in een JSON-string, wordt een string gecodeerd; als je dat resultaat één keer ontleedt, krijg je een string terug en geen object.
Belangrijkste punten
JSON.stringifygeeft meestal JSON-tekst terug; niet-ondersteunde waarden op het hoogste niveau kunnenundefinedopleveren.- Niet-ondersteunde objecteigenschappen verdwijnen, terwijl niet-ondersteunde arrayitems
nullworden. - Datums worden strings; Map en Set hebben expliciete conversie nodig.
- Circulaire structuren en gewone BigInts werpen een
TypeErrorop. - Vervangingsargumenten en
toJSONbepalen de geschreven weergave. - JSON-tekst opnieuw omzetten met stringify codeert een string, niet het object in die tekst.
5.3 Zet JSON-tekst om in waarden met JSON.parse
JSON.parse leest JSON-tekst en geeft de waarde terug die de tekst beschrijft. Ontleden controleert de syntaxis van de tekst; controleren of het resultaat bij je programma past, is een afzonderlijke taak.
Lees de waarde en bekijk daarna de velden
const data = JSON.parse('{"city":"Lima","tempC":19.5}');
data.tempC + 1; // 20.5
De buitenste enkele aanhalingstekens begrenzen een JavaScript-string. De dubbele aanhalingstekens daarin horen bij JSON. Ontleden maakt een gewoon object met een numerieke eigenschap tempC. Tekst die een array beschrijft, levert een array op; primitieve JSON-teksten leveren de bijbehorende primitieve waarden op.
Gegevens die al een object zijn, hoef je niet te ontleden. JSON.parse({ a: 1 }) zet dat argument eerst om in "[object Object]" en werpt dan een SyntaxError op. JSON.parse(undefined) mislukt ook omdat "undefined" geen geldige JSON-tekst is.
Handel ongeldige tekst af
function safeParse(text, fallback) {
try {
return JSON.parse(text);
} catch (error) {
return fallback;
}
}
safeParse("{ok:true}", null); // null
Ongeldige invoer, waaronder een lege string, JSON-strings met enkele aanhalingstekens, sleutels zonder aanhalingstekens en komma's aan het einde, werpt een SyntaxError op. Door die fout op te vangen, geef je het programma een bewuste terugvaloptie in plaats van het te stoppen. Een succesvol ontlede null is ook mogelijk, dus kies hoe de aanroeper een terugvalwaarde van geldige gegevens kan onderscheiden als dat verschil van belang is.
Herstel geselecteerde waarden met een herstelcallback
Een datum die als tekst is opgeslagen, komt terug als string. Een array van sleutel-waardeparen blijft een array totdat new Map(pairs) die omzet in een Map. Functies die bij het schrijven zijn weggelaten, kunnen niet uit de resterende tekst worden hersteld.
const text = '{"title":"Dentist","due":"2026-03-01T09:00:00.000Z"}';
const event = JSON.parse(text, (key, value) =>
key === "due" ? new Date(value) : value
);
De herstelcallback bezoekt binnenste waarden vóór hun containers en eindigt met het hele resultaat onder sleutel "". Een teruggegeven waarde vervangt de huidige waarde. Als de callback undefined teruggeeft, wordt die eigenschap verwijderd; als de callback dit voor de hoofdwaarde teruggeeft, wordt het hele ontleedresultaat undefined. Als je voor andere sleutels return value vergeet, kun je dus de gegevens wissen die je wilde behouden.
Controleer de structuur en plan een heen-en-terugconversie
Geldige JSON kan nog steeds de verkeerde typen bevatten. Het ontleden van '{"temp":"19"}' laat een string over, dus zou data.temp + 1 samenvoegen tot "191". Controleer verplichte velden en typen, bijvoorbeeld met typeof data?.temp === "number", voordat je gaat rekenen. Converteer alleen met Number wanneer het bedoelde formaat een numerieke string toestaat; optionele ketenvorming en ?? kunnen velden opvangen die mogen ontbreken.
Voor const settings = { theme: "dark", volume: 0.8, recent: ["a.txt"] }; levert omzetting naar een string 48 tekens JSON-tekst op. Ontleden herstelt dezelfde veldgegevens, maar loaded === settings is onwaar omdat ontleden nieuwe objecten maakt. Een Date komt terug als string, een objecteigenschap met undefined verdwijnt en een niet-geconverteerde Set komt terug als {}. Converteer speciale waarden vóór het schrijven en herstel hun bedoelde typen na het lezen.
Belangrijkste punten
JSON.parseleest tekst en werpt eenSyntaxErrorop bij ongeldige JSON.- Succesvol ontleden controleert niet de verplichte velden of hun typen.
- Een herstelcallback bezoekt eerst de onderliggende waarden en moet de waarden teruggeven die je wilt behouden.
- Heen-en-terugconversies via JSON maken nieuwe objecten en behouden alleen gegevens die JSON kan weergeven.
- Herstel verzamelings- en datumtypen expliciet na het ontleden.
JavaScript-objecten en JSON: voorbeelden
1Volg een verzendrecord
16 stappen
- 1IntroductieBouw een record dat je kunt bekijken
Een zending combineert een ID, een bestemming en pakketrecords. Je bouwt de zending op, bekijkt de velden en volgt gedeelde en gekopieerde gegevens. Twee namen kunnen één referentie naar hetzelfde record bevatten en een oppervlakkige kopie deelt nog steeds geneste niveaus, zodat een bijwerking gegevens kan bereiken die je gescheiden wilde houden.
De voorbeelden met de zending lopen door over de dia's, tenzij een stap expliciet een afzonderlijk object maakt.
- 2VoorbeeldMaak de zending
const shipment = { id: "s12", destination: "Porto", delayMin: 0 };De literal maakt drie eigenschappen aan. Vertraging wordt gemeten in minuten, waarbij nul een geldige waarde is.
shipment.destinationleest"Porto". Const staat toe dat eigenschappen worden bijgewerkt. - 3VoorbeeldKies een veld terwijl het programma draait
const field = "destination"; shipment[field] = "Braga"; shipment.checked = true;Blokhaaknotatie evalueert field en werkt de eigenschap destination bij. De toewijzing voegt ook checked toe omdat die eigenschap nog niet bestond. De zending heeft nog steeds dezelfde identiteit; geen van beide bewerkingen vervangt het buitenste object. Als je
shipment.fieldzou schrijven, zou je in plaats daarvan een afzonderlijke eigenschap aanmaken die letterlijk"field"heet. - 4UitdagingLees een berekende naam
Wat leest
shipment[field]nu en heeft de zending een eigen eigenschap field?---reveal---
De expressie leest
"Braga". De variabele field bevat de sleutel"destination", dus zowel de bijwerking als de leesbewerking bereikt die eigenschap.Object.hasOwn(shipment, "field")is onwaar omdat er geen letterlijke eigenschap field is aangemaakt. Een variabele waarmee je een eigenschap kiest, wordt zelf geen onderdeel van het record. - 5UitlegControleer nul zonder die te verliezen
shipment.delayMinis nul, dus slaat een voorwaarde die controleert of de waarde truthy is haar instructies over. De eigenschap bestaat nog steeds.Object.hasOwn(shipment, "delayMin")geeft waar terug. Gebruik een controle op eigen eigenschappen voor opgeslagen velden; de operator in neemt ook overgeërfde eigenschappen mee. - 6VoorbeeldLees de sleutel-waardeparen
const pairs = Object.entries(shipment); const count = Object.keys(shipment).length;Er zijn nu vier eigen opsombare velden met strings als sleutels, waaronder checked. Entries geeft voor elk veld één
[key, value]-paar. Je kunt ze metfor (const [key, value] of pairs)doorlopen om beide onderdelen te bekijken. Een directe for...of-lus over het gewone object shipment zou een fout opwerpen omdat dat object niet itereerbaar is. - 7UitdagingOnderscheid bestaan van waarde
Stel dat
shipment.note = undefined;wordt toegevoegd. Wat gevenshipment.noteenObject.hasOwn(shipment, "note")terug?---reveal---
Ze geven undefined en true terug. De toewijzing maakt de eigenschap aan, ook al is de waarde undefined. Als je de eigenschap verwijdert, verandert het resultaat van de aanwezigheidscontrole in false, terwijl een latere leesbewerking nog steeds undefined oplevert. De waarde alleen kan deze twee situaties niet onderscheiden.
- 8AnalogieVolg twee routes naar één record
Een referentie werkt als een route naar een record: als je de route kopieert, krijg je een andere manier om dezelfde bestemming te bereiken. Er wordt geen tweede record opgebouwd.
const alias = shipment; alias.checked = false;shipment.checkedis nu ook false. Beide variabelenamen bereiken één object, dus isalias === shipmenttrue. Overeenkomende referenties verklaren de gedeelde bijwerking; er is geen synchronisatiestap tussen twee kopieën uitgevoerd. - 9VoorbeeldVoeg gegevens toe die een oppervlakkige kopie zal delen
shipment.packages = [{ massG: 450 }, { massG: 700 }]; const shallow = { ...shipment }; shallow.destination = "Faro"; shallow.packages[0].massG = 500;Het nieuwe buitenste record heeft een eigen bestemming, dus blijft
shipment.destinationBraga. De waarde van packages is dezelfde arrayreferentie als voorheen. Als je dat gedeelde pad volgt, verandert ook de massa van het eerste pakket in de oorspronkelijke zending in 500. - 10VoorbeeldMaak een ondersteunde diepe kopie
const deep = structuredClone(shipment); deep.packages[0].massG = 600;Het eerste oorspronkelijke pakket blijft op 500 g omdat de diepe kopie een eigen geneste array en eigen pakketobjecten heeft. Dit record bevat alleen ondersteunde gegevens. Als het een eigenschap met een functie als waarde zou bevatten, zou structuredClone een DataCloneError opwerpen in plaats van die methode ongemerkt weg te laten.
- 11UitdagingVoorspel de grens van bevriezen
Voer deze instructies uit. Werpt de geneste toewijzing een fout op en wat is daarna de tweede massa?
Object.freeze(shipment); shipment.packages[1].massG = 750;---reveal---
De toewijzing slaagt en stelt de massa in op 750. Het bevriezen van shipment beschermt de eigen eigenschappen, maar niet de array waarnaar wordt verwezen of de records daarin. Een hertoewijzing van
shipment.destinationzou in strikte modus een TypeError opwerpen; deze geneste toewijzing bereikt een ander, niet-bevroren object. - 12VoorbeeldBereken het huidige totaal
const totalG = shipment.packages.reduce( (sum, pack) => sum + pack.massG, 0 );Na de vorige bijwerkingen bevat de oorspronkelijke zending massa's van 500 en 750 g. Reduce begint bij nul, telt er 500 en daarna 750 bij op, wat 1.250 oplevert. Het totaal wordt berekend uit de huidige pakketten. Als hun massa's later veranderen, voer je de berekening opnieuw uit; dit opgeslagen getal wordt niet vanzelf opnieuw berekend.
- 13TipVang een optioneel pad op
const contactName = shipment.contact?.name ?? "Unassigned";Er is geen eigenschap contact in het record, dus levert optionele ketenvorming undefined op en geeft de terugvaloptie
"Unassigned". Dit pad mag ontbreken. Houd verplichte velden zichtbaar voor validatie in plaats van alle fouten ongemerkt met standaardwaarden op te vangen. De terugval bij null of undefined behoudt ook een bewust lege naam, anders dan een terugval met logische OF. - 14UitdagingBehoud een geldige nul
Wat geven
shipment.delayMin ?? 10enshipment.delayMin || 10terug?---reveal---
De eerste geeft 0 terug; de tweede geeft 10 terug. Terugval bij null of undefined vervangt alleen null of undefined, terwijl logische OF elke falsy-waarde vervangt. Voor deze zending is een vertraging van nul minuten geregistreerd, dus als je die als ontbrekend behandelt, voeg je een vertraging toe die de opgeslagen gegevens nooit hebben vermeld.
- 15UitdagingCombineer een kopie met een optionele bijwerking
Er wordt een nieuw record gemaakt met
const next = { ...shipment };, gevolgd doornext.packages[0].massG = 520;. Wat gebeurt er met de eerste massa van shipment en is next hetzelfde buitenste object?---reveal---
De oorspronkelijke massa wordt 520 omdat de geneste array wordt gedeeld.
next === shipmentis false omdat spreadsyntaxis een nieuw buitenste object heeft gemaakt. Als je het buitenste record kopieert, staan toewijzingen aan de eigen eigenschappen los van elkaar, maar wordt niet een heel genest pad onafhankelijk. - 16SamenvattingKies de controle voor de taak
Kies een eigenschap met een letterlijke of berekende sleutel en onderscheid bestaan van de vraag of een waarde truthy is. Volg vóór een bijwerking of het pad gedeelde gegevens bereikt.
Kopieer geneste niveaus die onafhankelijk moeten zijn. Bereken afgeleide totalen opnieuw nadat hun invoer verandert.
2Houd een actie verbonden met haar object
12 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieVolg een actie terwijl die wordt doorgegeven
- 2VoorbeeldMaak een actie en roep die aan
- 3UitdagingLees de actie zonder die uit te voeren
- 4VoorbeeldLeen de gewone functie
- 5UitdagingKoppel de geleende methode los
- 6KernpuntZet een pijlfunctie binnen de methode
- 7VoorbeeldOmhul de benodigde aanroep
- 8VoorbeeldBind een callback één keer
- 9UitdagingKies directe of latere uitvoering
- 10TipGeef een bestaande binding voorrang
- 11UitdagingVolg een gebonden methode via een ander object
- 12SamenvattingLees de aanroepvorm
3Pak opties uit en bouw een bijgewerkt record
14 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieLees compacte syntaxis in kleine stappen
- 2VoorbeeldSelecteer en hernoem velden
- 3VoorbeeldGa een genest patroon binnen
- 4UitdagingLees een hernoemd genest veld
- 5UitdagingOnderscheid null van een ontbrekende waarde
- 6VoorbeeldPak een teruggegeven bereik uit
- 7VoorbeeldVerzamel de rest in een eigen array
- 8UitdagingVerwissel waarden voordat je ze gebruikt
- 9VoorbeeldVoeg standaardwaarden en vervangende waarden samen
- 10VoorbeeldKopieer het geneste niveau dat verandert
- 11VerbandLaat een veld weg uit het nieuwe record
- 12UitdagingKies een onafhankelijke bijwerking
- 13UitdagingVerbind patronen voor sleutel-waardeparen met spreadsyntaxis
- 14SamenvattingBepaal de taak voordat je waarden volgt
4Volg tellingen en unieke aanwezigheid
11 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieKies wat de verzameling moet onthouden
- 2VoorbeeldMaak tellingen met Map-methoden
- 3TipHoud sleutel-waardeparen gescheiden van eigenschappen
- 4UitdagingHoud sleuteltypen verschillend
- 5VoorbeeldHergebruik een objectsleutel
- 6VoorbeeldVerzamel unieke labels
- 7UitdagingBepaal of records dubbel zijn
- 8VoorbeeldZoek de gedeelde en ontbrekende labels
- 9KernpuntStel een andere vraag over aanwezigheid
- 10UitdagingVerbind tellingen met aanwezigheid
- 11SamenvattingStem de structuur af op de bewerking
5Schrijf, lees en controleer JSON-gegevens
14 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductiePlan beide richtingen van de conversie
- 2UitlegLees tekst als tekst
- 3UitdagingLos een syntaxisprobleem op
- 4VoorbeeldBekijk de actieve instellingen
- 5VoorbeeldConverteer de verzameling vóór het schrijven
- 6TipLaat de serialisatiefunctie escapesequenties in strings aanbrengen
- 7UitdagingVoorspel wat er met een niet-ondersteund arrayitem gebeurt
- 8VoorbeeldOntleed en herstel de aanwezigheidscontrole
- 9VoorbeeldHandel ongeldige tekst bewust af
- 10UitdagingControleer een geldige maar ongeschikte waarde
- 11UitlegHerstel één veld met een herstelcallback
- 12UitdagingBehoud het onderscheid tussen Map-sleutels
- 13VerbandHoud klonen en uitwisselen gescheiden
- 14SamenvattingControleer syntaxis, structuur en weergave
JavaScript-objecten en JSON: oefenvragen
Set 1: Lees records en volg waarden10 Oefenvragen
Vraag 1 van 10
Wat geeft sensor[field] terug?
const sensor = { tempC: 16, field: "room" };
const field = "tempC";
Toon antwoordVerberg antwoord
"tempC", om de eigenschap met waarde 16 te selecteren. Puntnotatie in sensor.field zou daarentegen de letterlijke eigenschap field lezen en "room" teruggeven.Vraag 2 van 10
Wat geeft Object.hasOwn(record, "enabled") terug?
const record = { enabled: false };
Toon antwoordVerberg antwoord
Vraag 3 van 10
Wat zijn record.region en record.key?
const key = "region";
const record = { [key]: "east" };
record[key] = "west";
Toon antwoordVerberg antwoord
"west". Er wordt geen letterlijke eigenschap key aangemaakt, dus geeft het lezen van record.key undefined terug.Vraag 4 van 10
Wat is meter.value na deze aanroep?
const meter = {
value: 7,
add() { this.value += 3; }
};
meter.add();
Toon antwoordVerberg antwoord
Vraag 5 van 10
Wat geeft right.read() terug?
const left = { name: "Ivo", read() { return this.name; } };
const right = { name: "Nia", read: left.read };
Toon antwoordVerberg antwoord
right aangeroepen, dus is this gelijk aan right en is de teruggegeven naam "Nia". De functie is oorspronkelijk in left geschreven, maar die plaats bindt het ontvangende object niet. Als de functie "Ivo" zou teruggeven, zou de oorspronkelijke opslagplaats worden verward met het object dat bij de huidige aanroep wordt gebruikt.Vraag 6 van 10
Wat zijn title en score na destructurering?
const { name: title, score = 8 } = { name: "Reef", score: null };
Toon antwoordVerberg antwoord
name in de lokale variabele title. De standaardwaarde voor score wordt alleen gebruikt bij undefined, dus blijft de expliciete null behouden. Als je null door 8 zou vervangen, zou je de ruimere regel voor terugval bij null of undefined toepassen op destructurering, die alleen bij undefined een standaardwaarde gebruikt.Vraag 7 van 10
Welke waarde krijgt third?
const [, , third] = [4, 9, 12, 18];
Toon antwoordVerberg antwoord
Vraag 8 van 10
Wat zijn m.size en m.get(2)?
const m = new Map([[2, "number"], ["2", "text"]]);
Toon antwoordVerberg antwoord
"2" twee afzonderlijke sleutel-waardeparen in. Het opzoeken van het getal 2 geeft "number" terug. Een grootte van 1 zou ontstaan als beide sleutels als dezelfde string werden behandeld, zoals deze namen zich gedragen als gewone objecteigenschappen.Vraag 9 van 10
Toon antwoordVerberg antwoord
Vraag 10 van 10
Welke tekst wordt teruggegeven?
JSON.stringify({
note: undefined,
values: [undefined, NaN],
ok: false
});
Toon antwoordVerberg antwoord
note als null zou worden behouden, zou de arrayregel ten onrechte op een objecteigenschap worden toegepast; het verwijderen van arrayposities zou de structuur veranderen.Set 2: Pas patronen toe en behoud ontvangende objecten10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Wat geeft trip.host?.name ?? "Guest" terug?
const trip = { host: null };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
Wat zijn de uiteindelijke waarden van a.level en a === b?
const a = { level: 2 };
const b = a;
b.level = 5;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
Wat zijn source.mode en source.layout.width daarna?
const source = { mode: "day", layout: { width: 40 } };
const copy = { ...source };
copy.mode = "night";
copy.layout.width = 60;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Welke functie kun je aan map doorgeven zodat elke aanroep tally bijwerkt?
const tally = { n: 0, tick() { return ++this.n; } };
const result = ["x", "y"].map(/* callback */);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Deze code wordt uitgevoerd op het hoogste niveau van een module. Wat gebeurt er als card.read() wordt aangeroepen?
const card = { title: "Basin", read: () => this.title };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
Wat zijn na next.panel.width = 90 de waarden van next.mode en base.panel.width?
const base = { mode: "wide", panel: { width: 50 } };
const next = { mode: "small", ...base, panel: { ...base.panel } };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Welke waarde krijgt size?
const { size = 6 } = {};
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
Welke array levert deze expressie op?
[...new Set(["red", "blue", "red", "green", "blue"])];
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
Wat is de uiteindelijke waarde van loaded?
const loaded = JSON.parse('{"count":4,"tag":"a"}', (key, value) => {
if (key === "count") return value * 2;
});
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Wat gebeurt er wanneer deze tekst wordt ontleed?
JSON.parse('{"mode":"fast","mode":"slow"}');
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 3: Transformeer verzamelingen en herstel gegevens10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Welk object maakt de expressie?
Object.fromEntries(
Object.entries({ north: 3, south: 5 })
.map(([key, value]) => [key, value + 2])
);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
Wat geeft options.limit ?? 12 terug?
const options = { limit: 0 };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
Wat moet add teruggeven zodat basket.add("pear").add("fig") twee keer dezelfde mand gebruikt?
const basket = {
items: [],
add(item) { this.items.push(item); /* return here */ }
};
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Welke array wordt in deze module teruggegeven?
function scale(n) { return this.factor * n; }
const twice = scale.bind({ factor: 2 });
const obj = { factor: 9, twice };
[obj.twice(3), twice.call({ factor: 5 }, 4)];
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Wat wordt teruggegeven?
function combine(first, ...others) {
return [first, others.length];
}
combine(...[7, 3, 8, 2]);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
Wat zijn items[0].done, next[1] === items[1] en next === items?
const items = [{ id: 4, done: false }, { id: 9, done: false }];
const next = items.map(item =>
item.id === 4 ? { ...item, done: true } : item
);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Waarom is lookup.get({ code: 8 }) undefined?
const key = { code: 8 };
const lookup = new Map([[key, "ready"]]);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
Wat zijn de grootten van a.difference(b) en a.symmetricDifference(b)?
const a = new Set([2, 4, 6]);
const b = new Set([4, 8]);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
Welke tekst levert dit op?
JSON.stringify({ label: "Arc", count: 3 }, ["label"]);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Deze module wordt uitgevoerd zonder herstelcallback. Wat zijn typeof loaded.due en loaded === original?
const original = { due: new Date("2026-07-12T00:00:00.000Z") };
const loaded = JSON.parse(JSON.stringify(original));
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 4: Onderzoek bijwerkingen en aanroepen10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Wat zijn base.inner.n, clone.inner.n en copy.inner.n aan het einde?
const base = { inner: { n: 2 } };
const copy = { ...base };
const clone = structuredClone(base);
Object.freeze(base);
copy.inner.n = 7;
clone.inner.n = 9;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
Welke array geeft Object.keys(data) terug?
const data = { z: 1, "10": 2, "02": 3, "2": 4, a: 5 };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
Wat is totalG en verandert load.items[1].massG ook als je heavy.massG wijzigt?
const load = { items: [
{ massG: 120, qty: 2 },
{ massG: 300, qty: 1 }
] };
const heavy = load.items.find(x => x.massG > 200);
const totalG = load.items.reduce((s, x) => s + x.massG * x.qty, 0);
heavy.massG = 350;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Wat geeft b.labels() terug in deze module?
const a = {
prefix: "A",
names: ["oak"],
labels() { return this.names.map(n => this.prefix + n); }
};
const b = { prefix: "B", names: ["elm"], labels: a.labels };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Wat is typeof box.open?
const box = { open() { return "opened"; } };
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
Wat gebeurt er als read() en read({ prefs: null }) afzonderlijk worden aangeroepen?
function read({ prefs: { theme = "light" } = {} } = {}) {
return theme;
}
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Wat is tail?
const [head, ...tail] = [6, 8, 11];
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
Wat zijn m.size en [...m.keys()]?
const m = new Map([["p", 1], ["q", 2]]);
m.set("p", 4);
m["r"] = 5;
m.delete("q");
m.set("q", 6);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
JSON.parse('{"depthM":+7}')?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Wat zijn result.count en result.total?
const result = JSON.parse('{"count":"6","total":12}',
(key, value) => key === "count" ? Number(value) : value
);
result.total += result.count;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 5: Combineer gegevenskeuzes en conversieregels10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Wat is Object.hasOwn(record, "old") na deze instructies?
const record = { old: undefined };
delete record.old;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
Wat zijn a === b, a.left === a.right en b.left === b.right?
const shared = { n: 1 };
const a = { left: shared, right: shared };
const b = JSON.parse(JSON.stringify(a));
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
Wat geeft saved() terug?
const maker = {
n: 5,
make() { return () => this.n; }
};
const other = { n: 8, make: maker.make };
const saved = other.make().bind({ n: 12 });
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Wat geeft fixed.apply({ offset: 30 }, [4]) terug?
function add(a, b) { return this.offset + a + b; }
const fixed = add.bind({ offset: 2 }, 7);
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Wat zijn a, b en rest?
let a = 3, b = 8;
[a, b] = [b, a];
const [, ...rest] = [a, b, 13];
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
Wat is na publicCopy.profile.name = "New" de waarde van source.profile.name en heeft source nog steeds secret als eigen eigenschap?
const source = { secret: "s", profile: { name: "Old" } };
const { secret, ...publicCopy } = source;
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Wat is de uiteindelijke waarde van counts.get("moss")?
const counts = new Map();
for (const word of ["moss", "fern", "moss", "moss"]) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
Wat zijn records.size en ids.size?
const x = { id: 7 };
const records = new Set([x, x, { id: 7 }]);
const ids = new Set([...records].map(r => r.id));
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
Wat is typeof JSON.parse(text)?
const text = JSON.stringify('{"x":3}');
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
"3" met de waarden "n" en "s" behouden. Welk paar conversies behoudt ze via JSON?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Kom je niet uit je eigen opgave? Huiswerkhulp
Kernbegrippen
A
Aanwezigheid van een eigenschap
count: 0 heeft nog steeds een eigenschap count; als je die waarde als voorwaarde test, merk je de eigenschap niet op.Aanwezigheidscontrole
map.has(key) kan een bestaand sleutel-waardepaar vinden, ook als map.get(key) undefined teruggeeft.Afgeleide waarde
apply
format.apply(reading, ["m", 2]) levert hetzelfde ontvangende object en dezelfde waarden als format.call(reading, "m", 2).Array-indexsleutel
"3" komt in Object.keys vóór "12"; "03" blijft tussen de gewone stringsleutels staan.Arraydestructurering
const [low, high] = bounds; vertrouwt erop dat bounds de lagere waarde vóór de hogere waarde plaatst.B
Berekende eigenschapsnaam
const code = "es"; maakt { [code]: "Hola" } een eigenschap met de naam "es".Bijwerking zonder mutatie
bind
const next = meter.step.bind(meter); maak je een callback die meter als ontvangend object behoudt.Blokhaaknotatie
const field = "heightM"; selecteert person[field] de lengtemeting van de persoon.C
call
format.call(reading, "m", 2) geeft format het ontvangende object reading en twee afzonderlijke argumenten.Circulaire referentie
record.self = record toevoegt, werpt het gewone JSON.stringify voor dat record een TypeError op.D
Deelverzameling
Diepe kopie
structuredClone blijft het oorspronkelijke geneste veld ongewijzigd als je het gekopieerde veld bewerkt.Doorsnede
E
Eigen eigenschap
Object.hasOwn({}, "toString") is false, ook al is "toString" in {} true.Eigenschap
active in { active: false } bestaat, ook al is haar waarde de booleaanse waarde false.Escapesequentie
G
Geleende methode
b.read = a.read zorgt ervoor dat b.read() de gegevens van b gebruikt wanneer de functie via this leest.Genest patroon
const { owner: { name } } = item; heeft een object owner nodig en declareert alleen name.Geneste gegevens
report.readings[0].tempC leest een lijst, het eerste record daarvan en vervolgens een temperatuurveld.Gewone functieaanroep in strikte modus
f en f() in een module aanroept, kan dat mislukken wanneer de functie this.name probeert te lezen.globalThis
H
Heen-en-terugconversie
Hernoemingspatroon
const { title: label } = page; maakt label aan zonder een variabele met de naam title te declareren.Herstelcallback
JSON.parse die waarden na hun onderliggende waarden transformeert en de retourwaarden gebruikt om de bezochte waarden te vervangen of te verwijderen.I
Inspringargument
Invoegvolgorde
Itereerbare waarde
J
JSON
{"ready":true} beschrijft een record, terwijl true op zichzelf ook een geldige volledige JSON-tekst is.JSON-string
JSON.parse
JSON.parse leest JSON-tekst en geeft de weergegeven JavaScript-waarde terug; bij ongeldige tekst werpt de functie een SyntaxError op.JSON.stringify
JSON.stringify serialiseert ondersteunde JavaScript-waarden naar JSON-tekst en kan daarbij gegevens selecteren en leesbare inspringing toevoegen.JSON.stringify(settings, null, 2) schrijft een beter leesbare vorm zonder de weergegeven instellingen te veranderen.L
Lexicale this
Losgekoppelde methode
const read = sensor.read; behoudt de functie, maar read() levert sensor niet als ontvangend object.M
Map
"5" blijven afzonderlijke sleutel-waardeparen wanneer ze in dezelfde Map worden opgeslagen.Map.groupBy
Map.groupBy is een nieuwere methode die itereerbare items in arrays binnen een Map groepeert en daarbij het type en de identiteit van groepssleutels behoudt.Methode
tracker.advance() voert de actie van de tracker uit, terwijl het lezen van tracker.advance een functie teruggeeft.Methoden aaneenschakelen
list.add("a").add("b") werkt wanneer de eerste aanroep een object met de volgende methode add teruggeeft.O
Object.freeze
Object.freeze voorkomt toevoegingen, verwijderingen en wijzigingen van de eigen eigenschappen van een object, maar bevriest geen geneste objecten.Object.fromEntries
Object.fromEntries maakt een object uit sleutel-waardeparen en is daardoor nuttig na een transformatie van paren of van een geschikte Map.Object.groupBy
Object.groupBy is een nieuwere methode die itereerbare items in arrays groepeert onder door een callback gekozen sleutels in een object zonder prototype.Objectdestructurering
const { city, tempC } = reading; maakt twee lokale variabelen uit een weerrecord.Objectidentiteit
id: 9 zijn bij vergelijking met === ongelijk, ondanks overeenkomende gegevens.Objectliteral
const reading = { tempC: 22 }; maakt een record met één temperatuurmeting.Omhullende pijlfunctie
() => counter.tick() aan map doorgeeft, roept elke callback tick via het object counter aan.Ontvangend object
account.describe() is account het ontvangende object waarvan de methode de velden leest.Oppervlakkige kopie
Optieobject
{ color, size } ontvangt, kunnen aanroepers aangeven wat elke instelling betekent zonder een vaste volgorde te gebruiken.Optionele ketenvorming
record.owner?.name staat een ontbrekende owner toe zonder een naam uit undefined te proberen te lezen.Overgeslagen positie
const [, second] = colors; slaat de eerste kleur over en geeft alleen de volgende geleverde waarde een naam.P
Partiële toepassing
multiply.bind(null, 4) maakt een functie die haar volgende argument met vier vermenigvuldigt.Puntnotatie
profile.name selecteert altijd de eigenschap met de naam "name", ook als er een variabele met de naam name bestaat.R
Referentie
const backup = record; geeft een extra manier om record te bereiken zonder de velden te kopiëren.Rest-element in een arraypatroon
const [leader, ...others] = names; scheidt de eerste naam van een array met de resterende namen.Restparameter
function total(...values) kan reduce gebruiken op values, ook als de aanroep geen argumenten doorgeeft.Restsyntaxis voor objecten
const { password, ...publicRecord } = user; laat user intact en laat password weg uit de kopie.S
Serialisatie
Set
"ready" twee keer toevoegt, blijft één waarde behouden, terwijl twee afzonderlijke overeenkomende records allebei behouden blijven.Sleutel-waardepaar
Object.entries({ lake: 5 }) levert [["lake", 5]] op, klaar voor een lus over sleutel en waarde.Sleutel-waardepaar in een Map
stock.set("tea", 4) wijzigt een sleutel-waardepaar; stock["tea"] = 4 wijzigt een gewone eigenschap.Spreadsyntaxis voor itereerbare waarden
Math.max(...measurements) geeft elk arrayitem als afzonderlijk argument door aan de functie.Spreadsyntaxis voor objecten
{ ...base, active: true } kopieert base en levert daarna de uiteindelijke waarde voor active.Standaardwaarde bij destructurering
const { count = 2 } = { count: null }; blijft de expliciete null behouden ondanks de standaardwaarde.structuredClone
Structuurcontrole
Symmetrisch verschil
SyntaxError
JSON.parse wordt doorgegeven.T
Terugval bij null of undefined
settings.volume ?? 1 behoudt een expliciet volume van nul, terwijl settings.volume || 1 dat vervangt.this
toJSON
V
Veilig geheel getal
Vereniging
Verkorte eigenschapsnotatie
city maakt de literal { city } hetzelfde veld als { city: city }.Verkorte methodenotatie
reset() { this.n = 0; } definieert een actie zonder afzonderlijke dubbele punt en sleutelwoord function.Verschil
active.difference(blocked) behoudt actieve waarden die niet in de Set blocked voorkomen.Vervangingsargument
W
WeakMap
WeakSet
Over deze les
Door StudeliFout melden
Maak je eigen Studiemateriaal
Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.