Functies als waarden
In JavaScript zijn functies gewoon waarden — net als getallen, strings en arrays. Je kunt ze opslaan in een variabele, meegeven als argument en teruggeven vanuit een functie.
// Functie opslaan in een variabele:
const begroet = function(naam) {
return `Hallo ${naam}!`;
};
// Functie opslaan als property van een object:
const acties = {
optellen: (a, b) => a + b,
aftrekken: (a, b) => a - b
};
console.log(acties.optellen(3, 4)); // 7
console.log(acties.aftrekken(10, 3)); // 7
Callbacks
Een callback is een functie die je meegeeft als argument aan een andere functie. Die andere functie roept jouw callback aan op het juiste moment.
function voerUit(functie) {
console.log('Voor de callback');
functie(); // roep de meegegeven functie aan
console.log('Na de callback');
}
function zegHallo() {
console.log('Hallo!');
}
voerUit(zegHallo);
// "Voor de callback"
// "Hallo!"
// "Na de callback"
Callback met argument
function verwerkNamen(namen, callback) {
for (const naam of namen) {
callback(naam);
}
}
verwerkNamen(['Anna', 'Bob', 'Carol'], (naam) => {
console.log(`Hallo ${naam}!`);
});
// "Hallo Anna!"
// "Hallo Bob!"
// "Hallo Carol!"
Callbacks ken je al
// setTimeout — callback na vertraging
setTimeout(() => {
console.log('1 seconde later');
}, 1000);
// addEventListener — callback bij event
knop.addEventListener('click', () => {
console.log('geklikt!');
});
// Array methods — callback voor elk element
[1, 2, 3].forEach(n => console.log(n));
[1, 2, 3].filter(n => n > 1);
Hogere orde functies
Een hogere orde functie is een functie die een andere functie accepteert als argument of teruggeeft als resultaat.
Functie accepteren
function pasToeTweeKeer(functie, waarde) {
return functie(functie(waarde));
}
const verdubbel = n => n * 2;
console.log(pasToeTweeKeer(verdubbel, 3)); // 12 (3 → 6 → 12)
Functie teruggeven
function maakVermenigvuldiger(factor) {
return function(getal) {
return getal * factor;
};
}
const verdubbel = maakVermenigvuldiger(2);
const verdriedubbel = maakVermenigvuldiger(3);
console.log(verdubbel(5)); // 10
console.log(verdriedubbel(5)); // 15
Eigen hogere orde functie
function filteredLog(array, filterFn) {
array
.filter(filterFn)
.forEach(item => console.log(item));
}
const getallen = [1, 2, 3, 4, 5, 6];
filteredLog(getallen, n => n % 2 === 0); // 2, 4, 6
filteredLog(getallen, n => n > 3); // 4, 5, 6
Closures
Een closure is een functie die toegang heeft tot variabelen van de buitenliggende scope, ook nadat die buitenliggende functie al is uitgevoerd.
function maakTeller() {
let teller = 0; // lokale variabele
return function() {
teller++;
return teller;
};
}
const tel = maakTeller();
console.log(tel()); // 1
console.log(tel()); // 2
console.log(tel()); // 3
// Aparte teller — eigen closure:
const tel2 = maakTeller();
console.log(tel2()); // 1 (begint opnieuw)
maakTeller()wordt uitgevoerd en is klaar- Toch onthoudt de teruggegeven functie de variabele
teller - Elke aanroep van
tel()werkt op dezelfdeteller tel2heeft zijn eigenteller— onafhankelijk
Closure met configuratie
function maakGreeter(groet) {
return function(naam) {
return `${groet} ${naam}!`;
};
}
const hallo = maakGreeter('Hallo');
const goedemorgen = maakGreeter('Goedemorgen');
console.log(hallo('Jan')); // "Hallo Jan!"
console.log(goedemorgen('Lisa')); // "Goedemorgen Lisa!"
Closure voor private staat
function maakBankRekening(beginSaldo) {
let saldo = beginSaldo; // privé — van buiten niet bereikbaar
return {
stortIn(bedrag) {
saldo += bedrag;
return saldo;
},
neemOp(bedrag) {
if (bedrag > saldo) return 'Onvoldoende saldo';
saldo -= bedrag;
return saldo;
},
getSaldo() {
return saldo;
}
};
}
const rekening = maakBankRekening(100);
rekening.stortIn(50);
console.log(rekening.getSaldo()); // 150
console.log(rekening.saldo); // undefined — privé!
Zie closures in actie
Drie counters naast elkaar — elk heeft zijn eigen count-variabele die door de closure wordt "vastgehouden". Klik +1 op counter 1: alleen die telt op. De andere blijven staan.
Drie keer aangeroepen → drie onafhankelijke counters:
Vergelijking: wat als count NIET in de functie zat?
Zet count buiten de functie (global) en kijk wat er gebeurt. Klik +1 op een knop hieronder — alle drie tellen op:
Drie "counters" delen nu dezelfde globale count:
Wat zie je? Klik op +1 bij Bad Counter 1 — alle drie de getallen springen tegelijk omhoog. Want er is maar één count variabele. Dat is precies de bug die closures oplossen.
Praktijkvoorbeelden
Debounce — niet te vaak uitvoeren
function debounce(functie, vertraging) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => functie(...args), vertraging);
};
}
// Zoekfunctie pas uitvoeren als gebruiker stopt met typen:
const zoek = debounce((zoekterm) => {
console.log(`Zoeken naar: ${zoekterm}`);
}, 300);
zoekVeld.addEventListener('input', (e) => zoek(e.target.value));
Once — slechts één keer uitvoeren
function eenmalig(functie) {
let uitgevoerd = false;
return function(...args) {
if (!uitgevoerd) {
uitgevoerd = true;
return functie(...args);
}
};
}
const initialiseer = eenmalig(() => {
console.log('App geïnitialiseerd!');
});
initialiseer(); // "App geïnitialiseerd!"
initialiseer(); // niets (al uitgevoerd)
Memoize — resultaten onthouden
function memoize(functie) {
const cache = {};
return function(arg) {
if (cache[arg] !== undefined) {
console.log('Uit cache!');
return cache[arg];
}
const resultaat = functie(arg);
cache[arg] = resultaat;
return resultaat;
};
}
const bereken = memoize((n) => {
console.log(`Berekening voor ${n}`);
return n * n;
});
bereken(5); // "Berekening voor 5" → 25
bereken(5); // "Uit cache!" → 25 (geen herberekening)
bereken(6); // "Berekening voor 6" → 36
Samenvatting
| Concept | Beschrijving |
|---|---|
| Functie als waarde | Functies zijn waarden die je kunt opslaan en doorgeven |
| Callback | Functie die als argument wordt meegegeven |
| Hogere orde functie | Functie die een functie accepteert of teruggeeft |
| Closure | Functie die variabelen van buitenliggende scope onthoudt |