Omdat functies achter de schermen objecten zijn, hebben ze een aantal eigenschappen en methoden. Een van deze eigenschappen is de this eigenschap.
De this eigenschap wordt geïnitialiseerd wanneer de functie wordt opgeroepen. De waarde die aan this wordt gebonden is afhankelijk van de manier waarop de functie wordt opgeroepen. Geef aan wat deze manieren zijn (er zijn er 3) en wat in dit geval de waarde van this is.
Als de functie die wordt opgeroepen een gewone (globale of lokale) functie is, dan zal this gelijk zijn aan “undefined” in strict mode en gelijk zijn aan het globaal object (het window object) in ‘sloppy’ mode.
Als de functie die wordt opgeroepen een methode van een object is, dan zal this verwijzen naar het object dat die methode heeft opgeroepen.
Arrow functies hebben geen this eigenschap. Dit wilt zeggen dat, Indien de arrow functie wordt opgeroepen en deze arrow functie het this keyword gebruikt in zijn body, dan zal deze this de waarde bevatten van de parent van de arrow functie.
Wat is de output van de volgende code en verklaar:
// object
const video = {
title: “a”,
tags: [“a”, “b”, “c”],
showTags() {
this.tags.forEach(function (tag) {
console.log(this.title, tag);
});
}, };//oproep van methode
video.showTags();
In normal mode is de output:
undefined 'a' undefined 'b' undefined 'c'
Dit is omdat in normal of ‘sloppy’ mode, de this waarde voor de callback functie gelijk is aan het window object. Omdat dit window object geen title eigenschap bevat, zal this.title resulteren in undefined.
In strict mode zal de deze code resulteren in een foutmelding. Dit is omdat in strict mode this gebonden zal worden aan undefined. this.title zal daarom ook resulteren in een foutmelding.
Omdat functies achter de schermen objecten zijn, hebben ze een aantal eigenschappen en methoden.
Drie van deze methoden hebben betrekking op de this eigenschap van de functie, namelijk: call, apply en bind.
Waarvoor dienen deze methoden en wat is het verschil tussen deze drie?
Alle drie methoden hebben als doel om de this waarde van de functie te initialiseren met de waarde dat wordt meegegeven als argument van de methoden. Bijvoorbeeld, stel we hebben de volgende functie:
function playVideo(x, y, z) {
console.log(this, x, y, z);
}
Als we nu bij oproep van de functie, de waarde voor this willen binden aan een bepaalde waarde (zoals bijvoorbeeld een object, dan kan dit aan de hand van call en apply:
playVideo.call({ name: “Jimmy” }, 1, 2, 3);
playVideo.apply({ name: “Jimmy” }, [1, 2, 3]);
beide methoden gaan de functie oproepen en hun this waarden binden aan de waarde dat als eerste argument wordt meegegeven. Merk op dat na het eerste argument van beide methoden een lijst van argumenten wordt meegegeven die zal doorgegeven worden aan de functie playVideo.
Hier zie je ook meteen het verschil tussen call en apply, namelijk: apply neemt deze argumenten mee als een array terwijl dit bij call niet moet.
De bind methode doet net hetzelfde als de call methode met als verschil dat het de functie playVideo niet meteen zal oproepen. Het is daarom ook niet nodig om de argumenten voor playVideo mee te geven aan de bind methode:
const foo = playVideo.bind({ name: “Jimmy” });
foo(1, 2, 3);
Hoe kan je een functie definiëren die een oneindig aantal argumenten kan hebben?
Er zijn twee manieren om dit te doen:
1. Door gebruik te maken van het argument object:
function sum() {
let sum = 0;
for (let val of arguments) {
sum += val;
}
return sum;
}
Merk op dat we de for-of loop normaal gebruiken om door een array te lopen maar dat we het in dit geval gebruiken om door een object te lopen. In normale omstandigheden zou dit niet gaan omdat gewone objecten geen iterable zijn. In dit geval gaat het echter wel omdat het arguments object een speciaal object is dat een iterable object wordt genoemd. Iterable objecten zijn objecten waarvoor een Symbol.iterator is gedefinieerd in hun body.
Belangrijk om te weten is dat arrow functies geen arguments object bevatten.
// de rest operator zal alle argumenten budnelen in een array met
// de naam values.
function sum(…values) {
let sum = 0;
for (let val of values) {
sum += val;
}
return sum;
}
wat ook kan is het volgende:
function TotalPrice(discount, …prices) {
}
In dit geval is het belangrijk dat de rest parameter altijd als laatste in de parameterlijst moet staat.
Hoe kan je default waarden voor de parameters van een functie definiëren?
Volgend voorbeeld laat zien hoe dit moet:
function calcInterest(lone, rate = 3.5, years = 5) {
return ((lone * rate) / 100) * years;
}
Belangrijk bij deze aanpak is dat wanneer je 1 parameter een default waarde geeft, dat alle parameters na deze parameter ook allemaal een default waarde moeten hebben. anders gezegd, parameters met default waarden komen altijd achteraan de parameterlijst.
Een closure is de bundeling van een functie en de toestand van de omgeving waarbinnen deze functie is aangemaakt. M.a.w. wanneer een functie wordt gedefinieerd, dan zal de functie ook de variabelen die in dezelfde omgeving zijn gedefinieerd onthouden. Volgend voorbeeld toont dit aan:
function foo() {
let ctr = 0;
return function () {
console.log(++ctr );
};
}
const faa = foo();
faa();
Hier merken we dat faa nog steeds toegang heeft tot de variabele ctr, ookal is de functie foo al reeds uitgevoerd, waardoor het van de callstack is gehaald, en waardoor de ctr variabele niet meer zou moeten bestaan.
Functies in javascript zijn eerste klas. Wat betekent dit?
Eerste klasse functies zijn functies die:
- We kunnen voorzien van een naam.
- We kunnen gebruiken als input van een andere functie.
- We kunnen teruggegeven als output van een andere functie.
Wat is het verschil tussen een functie declaratie en een functie expressie?
Een functie declaratie en expressie hebben de volgende verschillen:
de implementatie van een functie declaratie:
function foo(){
// body
}
De implementatie van en functie expressie:
const foo = function(){
// body
};
1.Een functie zonder naam.
(function () {
console.log(“Hello”);
})();
const calcAge = function(birthYear){
return 2037 - birthYear;
}
Deze functie gïmplementeerd als een arrow functie ziet er als volgt uit:
const calcAge = birthYear => 2037 - birthYear;
Merk op dat het niet nodig is om het return keyword in de arrow functie te plaatsen.
Een globale functie declaratie wordt steeds toegevoegd aan het window object. Zaken toevoegen aan het window object is echter afgeraden. Hoe kan je vermijden dat functies worden toegevoegd aan dit globaal object?
Door de functies te definiëren als functie expressies.