Entendre els tancaments de JavaScript en bucles: exemples pràctics

Entendre els tancaments de JavaScript en bucles: exemples pràctics
Entendre els tancaments de JavaScript en bucles: exemples pràctics

Desenvolupar tancaments de bucles en JavaScript

Els desenvolupadors de JavaScript sovint es troben amb un comportament inesperat quan utilitzen tancaments dins de bucles. Aquest problema pot generar confusió, especialment per a aquells que són nous en el concepte de tancaments.

En aquest article, explorarem exemples pràctics que il·lustren inconvenients comuns i proporcionen solucions per utilitzar tancaments de manera eficaç en bucles, ja sigui tractant amb escoltes d'esdeveniments, codi asíncron o iterant sobre matrius.

Comandament Descripció
let Declara una variable local d'abast de bloc, inicialitzant-la opcionalment a un valor. S'utilitza per assegurar que cada iteració del bucle té el seu propi abast.
const Declara una constant anomenada només de lectura amb àmbit de bloc. S'utilitza per crear una funció o variable el valor de la qual no hauria de canviar.
Promise Representa l'eventual finalització (o fallada) d'una operació asíncrona i el seu valor resultant.
setTimeout Crida una funció o avalua una expressió després d'un nombre especificat de mil·lisegons.
addEventListener Adjunta un controlador d'esdeveniments a un element especificat sense sobreescriure els controladors d'esdeveniments existents.
IIFE Expressió de funció invocada immediatament. Una funció que s'executa tan bon punt es defineix. S'utilitza per crear àmbits locals en bucles.
for...in Itera sobre les propietats enumerables d'un objecte, en un ordre arbitrari.
for...of Itera sobre els valors d'un objecte iterable (com una matriu o una cadena), en un ordre específic.

Entendre els tancaments de JavaScript en bucles

Els scripts que es proporcionen als exemples anteriors aborden el problema comú dels tancaments dins de bucles en JavaScript. Quan s'utilitza a var declaració dins d'un bucle, totes les iteracions comparteixen el mateix àmbit de funció. Per això, en el primer exemple, la sortida és "El meu valor: 3" tres vegades. La solució és utilitzar let, que crea un àmbit de bloc que manté el valor correcte per a cada iteració. Aquest enfocament garanteix que cada iteració tingui el seu propi abast, conservant així el valor correcte quan es crida la funció. L'script demostra com es canvia la declaració de var a let rectifica el problema i registra "El meu valor: 0", "El meu valor: 1" i "El meu valor: 2" tal com es pretén.

Per al codi asíncron, pot sorgir el mateix problema de tancament. Utilitzant Promises i setTimeout funcions amb let assegura que cada trucada asíncrona manté el valor d'iteració correcte. El guió ho mostra utilitzant wait amb let, cada promesa resolta registra el valor esperat. Els oients d'esdeveniments també poden enfrontar-se a problemes similars; tanmateix, embolicant la funció d'escolta en un IIFE (Expressió de funció invocada immediatament) ajuda a capturar el valor correcte creant un àmbit nou per a cada iteració. L'ús de for...in i for...of bucles demostra encara més la importància de l'abast en els tancaments, mostrant com capturar correctament l'índex i el valor utilitzant IIFE per crear àmbits diferents per a cada iteració del bucle.

Resolució de problemes de tancament en bucles JavaScript amb 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]();
}

Assegurar els valors de tancament correctes en codi asíncron

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

Tancament correcte als oients d'esdeveniments mitjançant 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);
}

Tancament correcte amb for...in i for...of Loops

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

Explorant l'ús de tancaments a les funcions avançades de JavaScript

Els tancaments són un concepte fonamental en JavaScript que permeten a una funció accedir a variables des del seu àmbit de tancament, fins i tot després que aquest àmbit s'hagi tancat. Aquesta característica és especialment potent quan es creen funcions avançades com les que s'utilitzen en la memorització, el curry i la programació funcional. Per exemple, la memorització aprofita els tancaments per recordar els resultats de les trucades de funcions cares i retornar el resultat de la memòria cau quan es tornen a produir les mateixes entrades. Mitjançant l'ús de tancaments, podem crear un codi més eficient i optimitzat que millori el rendiment, especialment en funcions recursives com el càlcul de seqüències de Fibonacci.

Un altre ús avançat dels tancaments és la creació de variables i funcions privades dins d'objectes JavaScript, simulant mètodes i propietats privades. Aquesta tècnica s'utilitza sovint en patrons de mòduls i expressions de funció invocades immediatament (IIFE) per encapsular la funcionalitat i evitar contaminar l'àmbit global. A més, els tancaments tenen un paper crucial en la gestió d'esdeveniments i la programació asíncrona, on ajuden a mantenir l'estat i el context al llarg del temps. Comprendre i utilitzar eficaçment els tancaments pot augmentar significativament les vostres habilitats de programació de JavaScript i us permetrà escriure codi més modular, reutilitzable i mantenible.

Preguntes freqüents sobre els tancaments de JavaScript

  1. Què és un tancament a JavaScript?
  2. Un tancament és una funció que conserva l'accés al seu àmbit lèxic, fins i tot quan la funció s'executa fora d'aquest àmbit.
  3. Per què es produeixen tancaments en bucles?
  4. Els tancaments en bucles es produeixen perquè el bucle crea funcions que capturen la mateixa referència de variable, provocant un comportament inesperat si no es gestiona correctament.
  5. Com podem solucionar els problemes de tancament en bucles?
  6. Utilitzant let en lloc de var en bucles o utilitzant IIFE (Expressions de funció invocades immediatament) poden solucionar problemes de tancament creant un àmbit nou per a cada iteració.
  7. Què és un IIFE?
  8. An IIFE és una funció que s'executa immediatament després de crear-la, sovint s'utilitza per crear un nou àmbit i evitar conflictes de variables.
  9. Els tancaments es poden utilitzar en programació asíncrona?
  10. Sí, els tancaments són essencials en la programació asíncrona per mantenir l'estat i el context en operacions asíncrones com ara promeses i devolució de trucades.
  11. Què és la memoització i com ajuden els tancaments?
  12. La memorització és una tècnica d'optimització per emmagatzemar a la memòria cau els resultats de trucades de funcions cares. Els tancaments ajuden conservant l'accés a la memòria cau a través de diverses trucades de funció.
  13. Com ajuden els tancaments en la gestió d'esdeveniments?
  14. Els tancaments conserven l'estat de les variables necessàries pels controladors d'esdeveniments, assegurant-se que funcionen correctament quan s'activa l'esdeveniment.
  15. Quin és el patró del mòdul a JavaScript?
  16. El patró del mòdul utilitza tancaments per crear variables i funcions privades, encapsulant la funcionalitat i evitant la contaminació d'abast global.
  17. Els tancaments poden simular mètodes privats en JavaScript?
  18. Sí, els tancaments poden simular mètodes privats mantenint les variables i funcions accessibles només dins de l'àmbit de la funció on es defineixen.

Consideracions finals sobre els tancaments de JavaScript en bucles

Dominar els tancaments en JavaScript, especialment en bucles, és crucial per escriure codi predictible i eficient. Mitjançant l'apalancament let, Promises, i IIFE, els desenvolupadors poden evitar inconvenients comuns i garantir un abast variable correcte. Aquesta comprensió millora la capacitat de gestionar tasques asíncrones i la programació basada en esdeveniments, donant lloc en última instància a aplicacions més robustes.