Forstå JavaScript-lukninger i løkker: Praktiske eksempler

JavaScript

Optrævning af løkkelukninger i JavaScript

JavaScript-udviklere støder ofte på uventet adfærd, når de bruger lukninger inde i løkker. Dette problem kan føre til forvirring, især for dem, der er nye med begrebet lukninger.

I denne artikel vil vi udforske praktiske eksempler, der illustrerer almindelige faldgruber og giver løsninger til at bruge lukninger effektivt i loops, uanset om det handler om begivenhedslyttere, asynkron kode eller iteration over arrays.

Kommando Beskrivelse
let Erklærer en lokal variabel med blokomfang, initialiserer den eventuelt til en værdi. Bruges til at sikre, at hver iteration af løkken har sit eget omfang.
const Erklærer en blok-omfattet, skrivebeskyttet navngivet konstant. Bruges til at oprette en funktion eller variabel, hvis værdi ikke skal ændres.
Promise Repræsenterer den endelige fuldførelse (eller fejl) af en asynkron operation og dens resulterende værdi.
setTimeout Kalder en funktion eller evaluerer et udtryk efter et angivet antal millisekunder.
addEventListener Vedhæfter en hændelseshandler til et specificeret element uden at overskrive eksisterende hændelseshandlere.
IIFE Umiddelbart påkaldt funktionsudtryk. En funktion, der kører, så snart den er defineret. Bruges til at skabe lokale scopes i loops.
for...in Itererer over et objekts utallige egenskaber i en vilkårlig rækkefølge.
for...of Itererer over værdierne af et itererbart objekt (som en matrix eller en streng) i en bestemt rækkefølge.

Forstå JavaScript-lukninger i løkker

Scripts i de foregående eksempler adresserer det almindelige problem med lukninger i loops i JavaScript. Ved brug af en erklæring inden for en løkke, deler alle iterationer det samme funktionsomfang. Derfor er outputtet i det første eksempel "Min værdi: 3" tre gange. Løsningen er at bruge , som opretter et blokomfang, der bevarer den korrekte værdi for hver iteration. Denne tilgang sikrer, at hver iteration har sit eget omfang, og dermed bevares den korrekte værdi, når funktionen kaldes. Scriptet demonstrerer, hvordan man ændrer erklæringen fra til let retter problemet og logger "Min værdi: 0", "Min værdi: 1" og "Min værdi: 2" efter hensigten.

For asynkron kode kan det samme lukningsproblem opstå. Ved brug af og fungerer med sikrer, at hvert asynkront opkald bevarer den korrekte iterationsværdi. Scriptet viser det ved at bruge wait med , hvert løst løfte logger den forventede værdi. Begivenhedslyttere kan også stå over for lignende problemer; dog at pakke lytterfunktionen ind i en (Umiddelbart aktiveret funktionsudtryk) hjælper med at indfange den korrekte værdi ved at skabe et nyt omfang for hver iteration. Brugen af og for...of loops demonstrerer yderligere vigtigheden af ​​scoping i lukninger og viser, hvordan man korrekt fanger indeks og værdi ved hjælp af for at skabe forskellige scopes for hver loop-iteration.

Løsning af lukkeproblemer i JavaScript-løkker med let

JavaScript (ES6)

let funcs = [];
// Let's create 3 functions
for (let i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value:", i);
  };
}
for (let j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

Sikring af korrekte lukkeværdier i asynkron kode

JavaScript (ES6)

const wait = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
for (let i = 0; i < 3; i++) {
  // Log `i` as soon as each promise resolves.
  wait(i * 100).then(() => console.log(i));
}

Korrekt lukning i begivenhedslyttere, der bruger IIFE

JavaScript (ES6)

var buttons = document.getElementsByTagName("button");
// Let's create 3 functions
for (var i = 0; i < buttons.length; i++) {
  // as event listeners
  (function(i) {
    buttons[i].addEventListener("click", function() {
      // each should log its value.
      console.log("My value:", i);
    });
  })(i);
}

Korrekt lukning med for ... i og for ... af løkker

JavaScript (ES6)

const arr = [1, 2, 3];
const fns = [];
for (const i in arr) {
  fns.push(((i) => () => console.log("index:", i))(i));
}
for (const v of arr) {
  fns.push(((v) => () => console.log("value:", v))(v));
}
for (const n of arr) {
  const obj = { number: n };
  fns.push(((n, obj) => () => console.log("n:", n, "|", "obj:", JSON.stringify(obj)))(n, obj));
}
for (const f of fns) {
  f();
}

Udforskning af brugen af ​​lukninger i avancerede JavaScript-funktioner

Lukninger er et grundlæggende koncept i JavaScript, der tillader en funktion at få adgang til variabler fra dets omsluttende omfang, selv efter at dette område er lukket. Denne funktion er særlig effektiv, når du opretter avancerede funktioner, såsom dem, der bruges i huskeseddel, currying og funktionel programmering. Memoization udnytter f.eks. lukninger til at huske resultaterne af dyre funktionskald og returnere det cachelagrede resultat, når de samme input forekommer igen. Ved at bruge lukninger kan vi skabe mere effektiv og optimeret kode, der forbedrer ydeevnen, især i rekursive funktioner som beregning af Fibonacci-sekvenser.

En anden avanceret anvendelse af lukninger er at skabe private variabler og funktioner i JavaScript-objekter, simulering af private metoder og egenskaber. Denne teknik bruges ofte i modulmønstre og umiddelbart påkaldte funktionsudtryk (IIFE) for at indkapsle funktionalitet og undgå at forurene det globale omfang. Desuden spiller lukninger en afgørende rolle i begivenhedshåndtering og asynkron programmering, hvor de hjælper med at bevare tilstand og kontekst over tid. Forståelse og effektiv udnyttelse af lukninger kan øge dine JavaScript-programmeringsfærdigheder betydeligt og gøre dig i stand til at skrive mere modulær, genbrugelig og vedligeholdelig kode.

  1. Hvad er en lukning i JavaScript?
  2. En lukning er en funktion, der bevarer adgangen til sit leksikale omfang, selv når funktionen udføres uden for dette omfang.
  3. Hvorfor opstår lukninger i løkker?
  4. Lukninger i sløjfer opstår, fordi sløjfen opretter funktioner, der fanger den samme variabelreference, hvilket fører til uventet adfærd, hvis den ikke håndteres korrekt.
  5. Hvordan kan vi løse lukningsproblemer i sløjfer?
  6. Ved brug af i stedet for i sløjfer eller vha (Umiddelbart påkaldte funktionsudtryk) kan løse lukningsproblemer ved at oprette et nyt omfang for hver iteration.
  7. Hvad er en IIFE?
  8. An er en funktion, der udføres umiddelbart efter den er oprettet, ofte brugt til at skabe et nyt omfang og undgå variable konflikter.
  9. Kan lukninger bruges i asynkron programmering?
  10. Ja, lukninger er afgørende i asynkron programmering for at opretholde tilstanden og konteksten på tværs af asynkrone operationer som løfter og tilbagekald.
  11. Hvad er huskeseddel, og hvordan hjælper lukninger?
  12. Memoisering er en optimeringsteknik til at cache resultaterne af dyre funktionskald. Lukninger hjælper ved at bevare adgangen til cachen på tværs af flere funktionsopkald.
  13. Hvordan hjælper lukninger til håndtering af begivenheder?
  14. Lukninger bevarer tilstanden for variabler, der er nødvendige af hændelseshandlere, og sikrer, at de fungerer korrekt, når hændelsen udløses.
  15. Hvad er modulmønsteret i JavaScript?
  16. Modulmønsteret bruger lukninger til at skabe private variabler og funktioner, indkapsle funktionalitet og undgå global forurening.
  17. Kan lukninger simulere private metoder i JavaScript?
  18. Ja, lukninger kan simulere private metoder ved kun at holde variabler og funktioner tilgængelige inden for funktionens omfang, hvor de er defineret.

At mestre lukninger i JavaScript, især inden for loops, er afgørende for at skrive forudsigelig og effektiv kode. Ved at udnytte , , og , kan udviklere undgå almindelige faldgruber og sikre korrekt variabel scoping. Denne forståelse forbedrer evnen til at håndtere asynkrone opgaver og hændelsesdrevet programmering, hvilket i sidste ende fører til mere robuste applikationer.