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
Dit principe — functies als "first-class citizens" — is de basis van callbacks, closures en hogere orde functies.
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);
Je gebruikt callbacks de hele tijd — bij events, timers en array methods. Nu weet je hoe dat mechanisme heet.
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)
Uitleg:
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é!
Closures worden veel gebruikt voor private staat, configureerbare functies en het bewaren van context.
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 |