I JavaScript er en funktion ikke en “magisk sproglig struktur”, men en særlig slags værdi.
Den syntaks, vi brugte før, kaldes en Funktionsdeklaration:
function sayHi() {
alert( "Hello" );
}
Der findes en anden syntaks til at oprette en funktion, som kaldes et Funktionsudtryk.
Det tillader os at oprette en ny funktion midt i en hvilken som helst udtryk.
For eksempel:
let sayHi = function() {
alert( "Hej" );
};
Her kan vi se en variabel sayHi få en værdi som er den nye funktion, oprettet som function() { alert("Hej"); }.
Da funktionen oprettes i kontekst af en tildeling (til højre for =), er dette et Funktionsudtryk.
Læg mærke til, at der ikke er noget navn efter function-nøgleordet. At udelade et navn er tilladt for Funktionsudtryk.
Her tildeler vi den straks til variablen, så betydningen af disse kodeeksempler er den samme: “opret en funktion og læg den i variablen sayHi”.
I mere avancerede situationer, som vi vil støde på senere, kan en funktion oprettes og straks kaldes eller planlægges til senere udførelse, uden at blive gemt nogen steder, og dermed forblive anonym.
Funktion er en værdi
Lad os gentage: uanset hvordan funktionen oprettes, er en funktion en værdi. Begge eksempler ovenfor gemmer en funktion i variablen sayHi.
Vi kan endda udskrive den værdi ved hjælp af alert:
function sayHi() {
alert( "Hej" );
}
alert( sayHi ); // viser funktionens kode
Vær opmærksom på, at den sidste linje ikke kører funktionen, fordi der ikke er nogen parenteser efter sayHi. Der findes programmeringssprog, hvor enhver omtale af et funktionsnavn forårsager dens udførelse, men JavaScript er ikke sådan.
I JavaScript er en funktion en værdi, så vi kan behandle den som en værdi. Koden ovenfor viser dens strengrepræsentation, som er kildekoden.
Med det sagt er en funktion en særlig værdi, i den forstand at vi kan kalde den som sayHi().
Men det er stadig en værdi. Så vi kan arbejde med den ligesom med andre slags værdier.
Vi kan kopiere en funktion til en anden variabel:
function sayHi() { // (1) opret
alert( "Hej" );
}
let func = sayHi; // (2) kopier
func(); // Hej // (3) kør kopien (det virker)!
sayHi(); // Hej // dette virker stadig også (hvorfor skulle det ikke)
Her er en detaljeret gennemgang af, hvad der sker ovenfor:
- Funktionsdeklarationen
(1)opretter funktionen og lægger den i variablen med navnetsayHi. - Linje
(2)kopierer den til variablenfunc. Bemærk igen: der er ingen parenteser eftersayHi. Hvis der var, villefunc = sayHi()skrive resultatet af kaldetsayHi()ind ifunc, ikke funktionensayHiselv. - Nu kan funktionen kaldes både som
sayHi()ogfunc().
Vi kunne også have brugt et Funktionsudtryk til at erklære sayHi i den første linje:
let sayHi = function() { // (1) opret
alert( "Hej" );
};
let func = sayHi; //(2)
// ...
Alt vil fungere på samme måde.
Du undrer dig måske over, hvorfor Funktionsudtryk har et semikolon ; til sidst, men Funktionsdeklarationer ikke har:
function sayHi() {
// ...
}
let sayHi = function() {
// ...
};
Svaret er simpelt: et Funktionsudtryk oprettes her som function(…) {…} inde i tildeling: let sayHi = …;. Semikolonet ; anbefales i slutningen af sætningen, det er ikke en del af funktionssyntaksen.
Et semikolon vil være der for en enklere tildeling, såsom let sayHi = 5;, og det er også på samme måde være der for en funktionstildeling.
Callback-funktioner
Lad os se flere eksempler på at videregive funktioner som værdier og bruge funktionsudtryk.
Vi vil skrive en funktion ask(question, yes, no) med tre parametre:
question- Teksten til spørgsmålet
yes- Funktion, der skal køres, hvis svaret er “Ja”
no- Funktion, der skal køres, hvis svaret er “Nej”
Funktionen skal stille question og, afhængigt af brugerens svar, kalde yes() eller no():
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "Du er enig." );
}
function showCancel() {
alert( "Du annullerede udførelsen." );
}
// brug: funktionerne showOk, showCancel videregives som argumenter til ask
ask("Er du enig?", showOk, showCancel);
I praksis er sådanne funktioner ret nyttige. Den største forskel mellem en virkelig ask og eksemplet ovenfor er, at virkelige funktioner bruger mere komplekse måder at interagere med brugeren på end en simpel confirm. I browseren tegner sådanne funktioner normalt et flot spørgsmålsvindue. Men det er en anden historie.
Argumenterne showOk og showCancel