In JavaScript is een functie geen “magische taalstructuur”, maar een speciaal soort waarde.

De syntaxis die we eerder gebruikten, heet een Functieverklaring:

function sayHi() { alert( "Hello" );}

Er is een andere syntaxis voor het maken van een functie die een Functie-uitdrukking wordt genoemd.

Het ziet er zo uit:

let sayHi = function() { alert( "Hello" );};

Hier wordt de functie expliciet gemaakt en aan de variabele toegewezen, net als elke andere waarde. Het maakt niet uit hoe de functie is gedefinieerd, het is gewoon een waarde die is opgeslagen in de variabele sayHi.

De betekenis van deze code-voorbeelden is hetzelfde: “maak een functie en stop die in de variabele sayHi“.

We kunnen die waarde zelfs uitprinten met alert:

function sayHi() { alert( "Hello" );}alert( sayHi ); // shows the function code

Merk op dat de laatste regel de functie niet uitvoert, omdat er geen haakjes staan na sayHi. Er zijn programmeertalen waar elke vermelding van een functienaam de uitvoering ervan veroorzaakt, maar JavaScript is niet zo.

In JavaScript is een functie een waarde, dus we kunnen er mee omgaan als een waarde. De code hierboven toont zijn string-representatie, dat is de broncode.

Zeker, een functie is een speciale waarde, in de zin dat we het kunnen noemen als sayHi().

Maar het is nog steeds een waarde. We kunnen er dus mee werken zoals met andere soorten waarden.

We kunnen een functie naar een andere variabele kopiëren:

function sayHi() { // (1) create alert( "Hello" );}let func = sayHi; // (2) copyfunc(); // Hello // (3) run the copy (it works)!sayHi(); // Hello // this still works too (why wouldn't it)

Hierboven staat in detail wat er gebeurt:

  1. De functiedeclaratie (1) creëert de functie en stopt deze in de variabele met de naam sayHi.
  2. Line (2) kopieert het naar de variabele func. Let nogmaals op: er staan geen haakjes na sayHi. Als die er wel waren, dan zou func = sayHi() het resultaat van de oproep sayHi() in func schrijven, niet de functie sayHi zelf.
  3. Nu kan de functie worden aangeroepen als zowel sayHi() als func().

Merk op dat we ook een Functie Expressie hadden kunnen gebruiken om sayHi aan te geven, in de eerste regel:

let sayHi = function() { alert( "Hello" );};let func = sayHi;// ...

Alles zou hetzelfde werken.

Waarom staat er een puntkomma aan het eind?

Je vraagt je misschien af, waarom heeft Functie Uitdrukking een puntkomma ; aan het eind, maar Functie Verklaring niet:

function sayHi() { // ...}let sayHi = function() { // ...};

Het antwoord is simpel:

  • Er is geen noodzaak voor ; aan het einde van codeblokken en syntaxstructuren die ze gebruiken, zoals if { ... }, for { }, function f { } enz.
  • Een functie-uitdrukking wordt gebruikt binnen het statement: let sayHi = ...;, als een waarde. Het is geen codeblok, maar eerder een toewijzing. De puntkomma ; wordt aanbevolen aan het eind van verklaringen, ongeacht wat de waarde is. Dus de puntkomma hier is niet gerelateerd aan de Functie Expressie zelf, het eindigt gewoon de verklaring.

Callback functies

Laten we eens kijken naar meer voorbeelden van het doorgeven van functies als waarden en het gebruik van functie expressies.

We schrijven een functie ask(question, yes, no) met drie parameters:

question Tekst van de vraag yes Functie die moet worden uitgevoerd als het antwoord “Ja” is no Functie die moet worden uitgevoerd als het antwoord “Nee” is

De functie moet de question vragen en, afhankelijk van het antwoord van de gebruiker, yes() of no() aanroepen:

function ask(question, yes, no) { if (confirm(question)) yes() else no();}function showOk() { alert( "You agreed." );}function showCancel() { alert( "You canceled the execution." );}// usage: functions showOk, showCancel are passed as arguments to askask("Do you agree?", showOk, showCancel);

In de praktijk zijn dergelijke functies heel nuttig. Het grote verschil tussen een echte ask en het bovenstaande voorbeeld is dat echte functies complexere manieren gebruiken om met de gebruiker te communiceren dan een eenvoudige confirm. In de browser tekent zo’n functie meestal een mooi vraagvenster. Maar dat is een ander verhaal.

De argumenten showOk en showCancel van ask worden callback functies of gewoon callbacks genoemd.

Het idee is dat we een functie doorgeven en verwachten dat die later wordt “teruggeroepen” als dat nodig is. In ons geval wordt showOk de callback voor “ja” antwoord, en showCancel voor “nee” antwoord.

We kunnen Functie Expressies gebruiken om dezelfde functie veel korter te schrijven:

function ask(question, yes, no) { if (confirm(question)) yes() else no();}ask( "Do you agree?", function() { alert("You agreed."); }, function() { alert("You canceled the execution."); });

Hier worden functies direct binnen de ask(...) aanroep gedeclareerd. Ze hebben geen naam, en worden dus anoniem genoemd. Dergelijke functies zijn niet toegankelijk buiten ask (omdat ze niet worden toegewezen aan variabelen), maar dat is precies wat we hier willen.

Zulke code verschijnt in onze scripts heel natuurlijk, het is in de geest van JavaScript.

Een functie is een waarde die een “actie “vertegenwoordigt.

Reguliere waarden zoals strings of getallen vertegenwoordigen de gegevens.

Een functie kan worden opgevat als een actie.

We kunnen het tussen variabelen doorgeven en uitvoeren wanneer we willen.

Functie-uitdrukking vs Functieverklaring

Laten we de belangrijkste verschillen tussen functieverklaringen en uitdrukkingen formuleren.

Eerst de syntaxis: hoe ze in de code van elkaar te onderscheiden.

  • Functieverklaring: een functie, verklaard als een afzonderlijk statement, in de hoofdcodestroom.

    // Function Declarationfunction sum(a, b) { return a + b;}

  • Functie-uitdrukking: een functie, gemaakt binnen een uitdrukking of binnen een ander syntaxisconstruct. Hier wordt de functie gemaakt aan de rechterkant van de “assignment expression” =:

    // Function Expressionlet sum = function(a, b) { return a + b;};

Het subtielere verschil is wanneer een functie wordt gemaakt door de JavaScript-engine.

Een functie-expressie wordt gemaakt wanneer de uitvoering het bereikt en is alleen vanaf dat moment bruikbaar.

Zodra de executiestroom naar de rechterkant van de toewijzing let sum = function… gaat – daar gaan we, is de functie gecreëerd en kan vanaf nu worden gebruikt (toegewezen, aangeroepen, enz. ).

Functieverklaringen zijn anders.

Een Functieverklaring kan eerder worden aangeroepen dan dat deze is gedefinieerd.

Een globale Functieverklaring is bijvoorbeeld zichtbaar in het hele script, ongeacht waar deze zich bevindt.

Dat komt door interne algoritmen. Wanneer JavaScript zich voorbereidt om het script uit te voeren, zoekt het eerst naar globale Functieverklaringen in het script en maakt de functies. We kunnen het zien als een “initialisatiefase”.

En nadat alle Functieverklaringen zijn verwerkt, wordt de code uitgevoerd. Het heeft dus toegang tot deze functies.

Voorbeeld werkt dit:

sayHi("John"); // Hello, Johnfunction sayHi(name) { alert( `Hello, ${name}` );}

De Functieverklaring sayHi wordt aangemaakt wanneer JavaScript zich voorbereidt om het script te starten en is overal in het script zichtbaar.

…Als het een Functie Expressie zou zijn, dan zou het niet werken:

sayHi("John"); // error!let sayHi = function(name) { // (*) no magic any more alert( `Hello, ${name}` );};

Functie Expressies worden aangemaakt als de uitvoering ze bereikt. Dat zou alleen gebeuren in de regel (*). Te laat.

Een andere speciale eigenschap van Functie Verklaringen is hun block scope.

In strict mode, wanneer een Functie Verklaring zich binnen een code blok bevindt, is het overal binnen dat blok zichtbaar. Maar niet daarbuiten.

Stellen we ons bijvoorbeeld voor dat we een functie welcome() moeten declareren die afhankelijk is van de variabele age die we tijdens runtime krijgen. En dan zijn we van plan om het enige tijd later te gebruiken.

Als we Functie Verklaring gebruiken, zal het niet werken zoals bedoeld:

let age = prompt("What is your age?", 18);// conditionally declare a functionif (age < 18) { function welcome() { alert("Hello!"); }} else { function welcome() { alert("Greetings!"); }}// ...use it laterwelcome(); // Error: welcome is not defined

Dat komt omdat een Functie Verklaring alleen zichtbaar is binnen het code blok waarin het zich bevindt.

Hier volgt nog een voorbeeld:

let age = 16; // take 16 as an exampleif (age < 18) { welcome(); // \ (runs) // | function welcome() { // | alert("Hello!"); // | Function Declaration is available } // | everywhere in the block where it's declared // | welcome(); // / (runs)} else { function welcome() { alert("Greetings!"); }}// Here we're out of curly braces,// so we can not see Function Declarations made inside of them.welcome(); // Error: welcome is not defined

Wat kunnen we doen om welcome zichtbaar te maken buiten if?

De juiste aanpak zou zijn om een Functie Expressie te gebruiken en welcome toe te wijzen aan de variabele die buiten if is gedeclareerd en de juiste zichtbaarheid heeft.

Deze code werkt zoals bedoeld:

let age = prompt("What is your age?", 18);let welcome;if (age < 18) { welcome = function() { alert("Hello!"); };} else { welcome = function() { alert("Greetings!"); };}welcome(); // ok now

Of we kunnen het nog verder vereenvoudigen met behulp van een vraagtekenoperator ?:

let age = prompt("What is your age?", 18);let welcome = (age < 18) ? function() { alert("Hello!"); } : function() { alert("Greetings!"); };welcome(); // ok now

Wanneer kiezen voor Functieverklaring versus Functie-uitdrukking?

Als vuistregel geldt: wanneer we een functie moeten declareren, moeten we in de eerste plaats de syntaxis Functieverklaring kiezen. Het geeft meer vrijheid in hoe we onze code organiseren, omdat we dergelijke functies kunnen aanroepen voordat ze zijn gedeclareerd.

Dat is ook beter voor de leesbaarheid, omdat het gemakkelijker is om function f(…) {…} in de code op te zoeken dan let f = function(…) {…};. Functieverklaringen springen meer “in het oog”.

…Maar als een Functieverklaring ons om een of andere reden niet uitkomt, of we hebben een voorwaardelijke verklaring nodig (we hebben net een voorbeeld gezien), dan moet een Functie-expressie worden gebruikt.

Samenvatting

  • Functies zijn waarden. Ze kunnen worden toegewezen, gekopieerd of gedeclareerd op elke plaats in de code.
  • Als de functie wordt gedeclareerd als een afzonderlijk statement in de hoofdcodestroom, wordt dat een “Functieverklaring” genoemd.
  • Als de functie wordt gemaakt als onderdeel van een expressie, wordt dat een “Functie-expressie” genoemd.
  • Functieverklaringen worden verwerkt voordat het codeblok wordt uitgevoerd. Ze zijn overal in het blok zichtbaar.
  • Functie Expressies worden gemaakt wanneer de uitvoeringsstroom ze bereikt.

In de meeste gevallen waarin we een functie moeten declareren, verdient een Functie Verklaring de voorkeur, omdat deze zichtbaar is voorafgaand aan de declaratie zelf. Dat geeft ons meer flexibiliteit in de organisatie van de code, en is meestal leesbaarder.

Dus moeten we een Functie Expressie alleen gebruiken als een Functie Verklaring niet geschikt is voor de taak. We hebben daar in dit hoofdstuk een paar voorbeelden van gezien, en we zullen er in de toekomst nog meer zien.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.