Closures i JavaScript
Denne artikkelen forklarer closures i JavaScript.
YouTube Video
Closures i JavaScript
I JavaScript er en «closure» et av de viktigste og kraftigste konseptene. Ved å forstå closures kan du tilegne deg kunnskap som er nyttig i mange situasjoner, som funksjoners oppførsel og omfang, samt JavaScripts asynkrone prosessering og hendelseshåndtering. Her vil vi forklare i detalj alt fra den grunnleggende definisjonen av closures til konkrete eksempler og bruksområder.
Hva er en Closure?
En closure refererer til mekanismen som gjør at en funksjon kan få tilgang til variabler i omfanget hvor den ble opprettet, selv om den kalles utenfor dette omfanget. Ved å benytte closures, blir det mulig for funksjoner å kontinuerlig 'huske' eksterne variabler.
Closures består av følgende to elementer.
-
Funksjonsdefinisjon (selve funksjonen)
-
Omfanget hvor funksjonen er definert (variabler og andre funksjoner utenfor selve funksjonen)
I JavaScript er closures mulig fordi funksjoner kan få tilgang til variabler i det omfanget de ble opprettet i.
Grunnleggende eksempel
Først, la oss se på et grunnleggende eksempel på en closure. I koden nedenfor returnerer outerFunction
en funksjon kalt innerFunction
. Det viktige poenget er at innerFunction
kan få tilgang til variabelen count
som er definert i omfanget til 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 closures fungerer
Som vist i eksemplet ovenfor beholdes count
av innerFunction
selv etter at outerFunction
er utført. innerFunction
kan fortsette å aksessere omfanget til outerFunction
, og derfor blir count
oppdatert inne i innerFunction
. Dette er den grunnleggende mekanismen til en closure.
Det er innerFunction
som er tildelt variabelen counter
, og vi kan se at tilstanden til count
bevares selv om outerFunction
allerede er ferdig utført. Dette er fordi JavaScript kontinuerlig 'husker' omfanget på tidspunktet for funksjonsdefinisjonen.
Bruk: Closures som private variabler
Closures kan brukes som 'private variabler' i objektorientert programmering. Normalt i JavaScript er objektets egenskaper direkte tilgjengelige fra utsiden, men ved bruk av closures kan man hindre direkte manipulering av variabler innenfor funksjonens omfang fra utsiden.
I neste eksempel bruker funksjonen createCounter
en closure for å lage en teller og returnerer en teller 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 eksemplet er count
i omfanget til funksjonen createCounter
, og kan derfor ikke nås direkte fra utsiden. Men den kan manipuleres via metodene increment
og decrement
. På denne måten kan du ved hjelp av closures implementere konseptet med private variabler i JavaScript.
Praktiske eksempler på closures
Kombinasjon med callback-funksjoner
Closures brukes ofte sammen med callback-funksjoner for å håndtere asynkron prosessering. La oss for eksempel se på et eksempel som bruker 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 eksemplet får funksjonen countdown
tilgang til variabelen timeLeft
i omfanget til startTimer
. På denne måten er closures svært nyttige for asynkron prosessering som timere, fordi de opprettholder tilstanden til variabler over tid.
Event handlers
Closures er også nyttige når du setter opp event handlers. I eksemplet nedenfor brukes en closure til å telle hvor mange ganger en knapp klikkes.
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 tilfellet øker clickCount
for hvert klikk, og verdien beholdes. Ved å bruke closures kan du tildele en egen teller til hver knapp.
Konklusjon
Closures er et konsept som symboliserer fleksibiliteten og styrken til JavaScript. De holder på variabler innenfor et funksjonsomfang og tillater operasjoner på disse variablene via funksjoner som er tilgjengelige utenfra. Ved å forstå og bruke denne mekanismen kan du tilegne deg mer avanserte teknikker i JavaScript-programmering.
Closures brukes i forskjellige situasjoner, fra hendelseshåndtering og asynkron prosessering til til og med pseudo-implementeringer av objektorientert programmering.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.