JavaScript-sluitingen in loops begrijpen: praktische voorbeelden

JavaScript-sluitingen in loops begrijpen: praktische voorbeelden
JavaScript-sluitingen in loops begrijpen: praktische voorbeelden

Het ontrafelen van lussluitingen in JavaScript

JavaScript-ontwikkelaars komen vaak onverwacht gedrag tegen bij het gebruik van sluitingen binnen lussen. Dit probleem kan tot verwarring leiden, vooral voor degenen die nieuw zijn met het concept van sluitingen.

In dit artikel onderzoeken we praktische voorbeelden die veelvoorkomende valkuilen illustreren en oplossingen bieden voor het effectief gebruiken van afsluitingen in lussen, of het nu gaat om gebeurtenislisteners, asynchrone code of iteratie over arrays.

Commando Beschrijving
let Declareert een lokale variabele met blokbereik en initialiseert deze optioneel op een waarde. Wordt gebruikt om ervoor te zorgen dat elke iteratie van de lus zijn eigen bereik heeft.
const Declareert een blokgerichte, alleen-lezen benoemde constante. Wordt gebruikt om een ​​functie of variabele te maken waarvan de waarde niet mag veranderen.
Promise Vertegenwoordigt de uiteindelijke voltooiing (of mislukking) van een asynchrone bewerking en de resulterende waarde ervan.
setTimeout Roept een functie aan of evalueert een uitdrukking na een opgegeven aantal milliseconden.
addEventListener Koppelt een gebeurtenishandler aan een opgegeven element zonder bestaande gebeurtenishandlers te overschrijven.
IIFE Onmiddellijk aangeroepen functie-expressie. Een functie die wordt uitgevoerd zodra deze is gedefinieerd. Wordt gebruikt om lokale bereiken in lussen te maken.
for...in Herhaalt de opsombare eigenschappen van een object, in een willekeurige volgorde.
for...of Herhaalt de waarden van een itereerbaar object (zoals een array of een tekenreeks), in een specifieke volgorde.

JavaScript-sluitingen in loops begrijpen

De scripts uit de voorgaande voorbeelden pakken het algemene probleem van sluitingen binnen lussen in JavaScript aan. Bij gebruik van een var declaratie binnen een lus delen alle iteraties hetzelfde functiebereik. Dit is de reden waarom in het eerste voorbeeld de uitvoer drie keer "Mijn waarde: 3" is. De oplossing is gebruiken let, waarmee een blokbereik wordt gemaakt dat voor elke iteratie de juiste waarde behoudt. Deze aanpak zorgt ervoor dat elke iteratie zijn eigen bereik heeft, waardoor de juiste waarde behouden blijft wanneer de functie wordt aangeroepen. Het script laat zien hoe u de declaratie wijzigt van var naar let verhelpt het probleem en registreert "Mijn waarde: 0", "Mijn waarde: 1" en "Mijn waarde: 2" zoals bedoeld.

Voor asynchrone code kan hetzelfde afsluitingsprobleem optreden. Gebruik makend van Promises En setTimeout functioneert met let zorgt ervoor dat elke asynchrone oproep de juiste iteratiewaarde behoudt. Het script laat dat zien door gebruik te maken van wait met let, registreert elke opgeloste belofte de verwachte waarde. Gebeurtenisluisteraars kunnen ook met soortgelijke problemen worden geconfronteerd; echter, het verpakken van de luisteraarfunctie in een IIFE (Immediately Invoked Function Expression) helpt bij het vastleggen van de juiste waarde door voor elke iteratie een nieuw bereik te creëren. Het gebruik van for...in En for...of loops demonstreert verder het belang van scoping bij sluitingen, en laat zien hoe index en waarde correct kunnen worden vastgelegd IIFE om verschillende scopes te creëren voor elke lus-iteratie.

Sluitingsproblemen in JavaScript-loops oplossen met 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]();
}

Zorgen voor correcte sluitingswaarden in asynchrone code

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));
}

Correcte afsluiting bij gebeurtenislisteners met behulp van 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);
}

Correcte sluiting met voor...in en voor...van lussen

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();
}

Onderzoek naar het gebruik van sluitingen in geavanceerde JavaScript-functies

Sluitingen zijn een fundamenteel concept in JavaScript waarmee een functie toegang kan krijgen tot variabelen uit het omsluitende bereik, zelfs nadat dat bereik is gesloten. Deze functie is vooral krachtig bij het creëren van geavanceerde functies zoals die worden gebruikt bij het onthouden, curryen en functioneel programmeren. Bij memoisatie wordt bijvoorbeeld gebruik gemaakt van sluitingen om de resultaten van dure functieaanroepen te onthouden en het in de cache opgeslagen resultaat terug te sturen wanneer dezelfde invoer opnieuw plaatsvindt. Door sluitingen te gebruiken, kunnen we efficiëntere en geoptimaliseerde code creëren die de prestaties verbetert, vooral bij recursieve functies zoals het berekenen van Fibonacci-reeksen.

Een ander geavanceerd gebruik van sluitingen is het creëren van privévariabelen en -functies binnen JavaScript-objecten, waarbij privémethoden en -eigenschappen worden gesimuleerd. Deze techniek wordt vaak gebruikt in modulepatronen en roept onmiddellijk functie-expressies (IIFE) op om functionaliteit in te kapselen en vervuiling van de mondiale reikwijdte te voorkomen. Bovendien spelen afsluitingen een cruciale rol bij het afhandelen van gebeurtenissen en bij asynchrone programmering, waarbij ze helpen de status en context in de loop van de tijd vast te houden. Het begrijpen en effectief gebruiken van afsluitingen kan uw JavaScript-programmeervaardigheden aanzienlijk verbeteren en u in staat stellen meer modulaire, herbruikbare en onderhoudbare code te schrijven.

Veelgestelde vragen over JavaScript-sluitingen

  1. Wat is een afsluiting in JavaScript?
  2. Een afsluiting is een functie die toegang behoudt tot zijn lexicale bereik, zelfs als de functie buiten dat bereik wordt uitgevoerd.
  3. Waarom vinden sluitingen plaats in lussen?
  4. Sluitingen in lussen treden op omdat de lus functies creëert die dezelfde variabelereferentie vastleggen, wat tot onverwacht gedrag leidt als het niet correct wordt afgehandeld.
  5. Hoe kunnen we sluitingsproblemen in lussen oplossen?
  6. Gebruik makend van let in plaats van var in lussen of met behulp van IIFE (Immediately Invoked Function Expressions) kunnen afsluitingsproblemen oplossen door voor elke iteratie een nieuw bereik te maken.
  7. Wat is een IIFE?
  8. Een IIFE is een functie die onmiddellijk wordt uitgevoerd nadat deze is gemaakt, vaak gebruikt om een ​​nieuw bereik te creëren en variabele conflicten te vermijden.
  9. Kunnen sluitingen worden gebruikt bij asynchrone programmering?
  10. Ja, sluitingen zijn essentieel bij asynchrone programmering om de status en context bij asynchrone bewerkingen, zoals beloftes en callbacks, te behouden.
  11. Wat is memoriseren en hoe kunnen sluitingen helpen?
  12. Memoiseren is een optimalisatietechniek om de resultaten van dure functieaanroepen in het cachegeheugen op te slaan. Sluitingen helpen door de toegang tot de cache te behouden voor meerdere functieaanroepen.
  13. Hoe kunnen sluitingen helpen bij de afhandeling van evenementen?
  14. Sluitingen behouden de status van variabelen die nodig zijn voor gebeurtenishandlers, zodat ze correct functioneren wanneer de gebeurtenis wordt geactiveerd.
  15. Wat is het modulepatroon in JavaScript?
  16. Het modulepatroon maakt gebruik van afsluitingen om privévariabelen en -functies te creëren, waardoor functionaliteit wordt ingekapseld en mondiale reikwijdtevervuiling wordt vermeden.
  17. Kunnen sluitingen privémethoden in JavaScript simuleren?
  18. Ja, afsluitingen kunnen privémethoden simuleren door variabelen en functies alleen toegankelijk te houden binnen het bereik van de functie waar ze zijn gedefinieerd.

Laatste gedachten over JavaScript-sluitingen in loops

Het beheersen van afsluitingen in JavaScript, vooral binnen loops, is cruciaal voor het schrijven van voorspelbare en efficiënte code. Door te benutten let, Promises, En IIFEkunnen ontwikkelaars veelvoorkomende valkuilen vermijden en zorgen voor een correcte variabele scoping. Dit inzicht vergroot het vermogen om asynchrone taken en gebeurtenisgestuurde programmering af te handelen, wat uiteindelijk leidt tot robuustere applicaties.