Closure i JavaScript

Closure i JavaScript

Denne artikel forklarer closure i JavaScript.

YouTube Video

Closure i JavaScript

I JavaScript er en 'lukning' et af de meget vigtige og kraftfulde begreber. Ved at forstå closure kan du opnå viden, der er nyttig i mange situationer, såsom funktioners opførsel og scope, samt JavaScripts asynkrone behandling og event-håndtering. Her vil vi detaljeret forklare alt fra den grundlæggende definition af closure til konkrete eksempler og deres anvendelser.

Hvad er en lukning?

En lukning henviser til den mekanisme, hvorved en funktion kan få adgang til variabler i dens oprettelses-scope, selv når den kaldes uden for dette scope. Ved at bruge closure bliver det muligt for funktioner løbende at 'huske' eksterne variabler.

Closure består af følgende to elementer.

  1. Funktionsdefinition (selve funktionen)

  2. Scope hvori funktionen er defineret (variabler og andre funktioner udenfor selve funktionen)

I JavaScript er closure mulige, fordi funktioner har evnen til at tilgå variabler inden for det scope, hvor de blev oprettet.

Basiseksempel

Lad os først kigge på et grundlæggende eksempel på en lukning. I følgende kode returnerer outerFunction en funktion kaldet innerFunction. Det vigtige er, at innerFunction kan få adgang til variablen count, som er defineret i scope'en for outerFunction.

 1function outerFunction() {
 2    let count = 0;
 3
 4    function innerFunction() {
 5        count++;
 6        console.log(`Current count: ${count}`);
 7    }
 8
 9    return innerFunction;
10}
11
12const counter = outerFunction();
13counter(); // Current count: 1
14counter(); // Current count: 2
15counter(); // Current count: 3

Hvordan closure virker

Som set i ovenstående eksempel bevares count af innerFunction, selv efter at outerFunction er blevet udført. innerFunction kan fortsat få adgang til scope'en for outerFunction, og derfor opdateres count indenfor innerFunction. Dette er den grundlæggende mekanisme bag en lukning.

Det er innerFunction, der tildeles variablen counter, og vi kan se, at tilstanden af count bevares, selv om outerFunction allerede er afsluttet. Dette skyldes, at JavaScript løbende 'husker' scope'en på det tidspunkt, hvor funktionen blev defineret.

Anvendelse: Closure som private variabler

Closure kan bruges som 'private variabler' i objektorienteret programmering. Normalt er objekt-egenskaber i JavaScript direkte tilgængelige udefra, men ved hjælp af closure er det muligt at forhindre direkte manipulation af variabler indenfor funktionsscope udefra.

I det næste eksempel bruger funktionen createCounter en lukning til at oprette en tæller og returnerer en tæller med en privat variabel count.

 1function createCounter() {
 2    let count = 0;
 3
 4    return {
 5        increment: function() {
 6            count++;
 7            console.log(`Count: ${count}`);
 8        },
 9        decrement: function() {
10            count--;
11            console.log(`Count: ${count}`);
12        },
13        getCount: function() {
14            return count;
15        }
16    };
17}
18
19const myCounter = createCounter();
20myCounter.increment(); // Count: 1
21myCounter.increment(); // Count: 2
22myCounter.decrement(); // Count: 1
23console.log(myCounter.getCount()); // 1

I dette eksempel er count i scope'en for funktionen createCounter, så den kan ikke tilgås direkte udefra. Men den kan manipuleres gennem metoderne increment og decrement. På denne måde kan du ved hjælp af closure inkorporere begrebet private variabler i JavaScript.

Praktiske eksempler på closure

Kombination med callback-funktioner

Closure bruges ofte sammen med callback-funktioner til at håndtere asynkron behandling. Lad os for eksempel se på et eksempel med en timer.

 1function startTimer(duration) {
 2    let timeLeft = duration;
 3
 4    function countdown() {
 5        console.log(`Time left: ${timeLeft} seconds`);
 6        timeLeft--;
 7
 8        if (timeLeft >= 0) {
 9            setTimeout(countdown, 1000);
10        }
11    }
12
13    countdown();
14}
15
16startTimer(5);
17// Time left: 5 seconds
18// Time left: 4 seconds
19// Time left: 3 seconds
20// Time left: 2 seconds
21// Time left: 1 second
22// Time left: 0 seconds

I dette eksempel tilgår funktionen countdown variablen timeLeft inden for scope'en af startTimer. På denne måde er closure meget nyttige til asynkron behandling som timere, fordi de kan fastholde variablers tilstand over tid.

Event handlers

Closure er også praktiske, når man sætter event handlers op. I det følgende eksempel bruges en lukning til at registrere hvor mange gange en knap er blevet klikket.

 1function setupClickCounter(buttonId) {
 2    let clickCount = 0;
 3
 4    const button = document.getElementById(buttonId);
 5    button.addEventListener('click', function() {
 6        clickCount++;
 7        console.log(`Button clicked ${clickCount} times`);
 8    });
 9}
10
11setupClickCounter('myButton');

I dette tilfælde øges clickCount for hvert klik, og værdien bevares. Ved at bruge closure kan du tildele en uafhængig tæller til hver knap.

Konklusion

Closure er et begreb, der symboliserer fleksibiliteten og styrken i JavaScript. De fastholder variabler, der er indesluttet i et funktionsscope, og gør det muligt at arbejde med disse variabler via funktioner, der kan tilgås udefra. Ved at forstå og udnytte denne mekanisme kan du tilegne dig mere avancerede teknikker i JavaScript-programmering.

Closure anvendes i forskellige situationer, fra event-håndtering og asynkron behandling til endda pseudo-implementeringer af objektorienteret programmering.

Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.

YouTube Video