Lietuvių

Išnagrinėkite JavaScript uždarąsias sritis (closures) pasitelkdami praktinius pavyzdžius, suprasdami, kaip jos veikia ir kaip pritaikomos realioje programinės įrangos kūrimo praktikoje.

JavaScript uždarosios sritys (Closures): paaiškinimas su praktiniais pavyzdžiais

Uždarosios sritys (closures) yra fundamentalus JavaScript konceptas, kuris dažnai kelia sumaištį įvairaus lygio programuotojams. Suprasti uždarąsias sritis yra itin svarbu norint rašyti efektyvų, prižiūrimą ir saugų kodą. Šis išsamus vadovas paaiškins uždarąsias sritis su praktiniais pavyzdžiais ir parodys jų pritaikymą realiame pasaulyje.

Kas yra uždaroji sritis (Closure)?

Paprasčiau tariant, uždaroji sritis yra funkcijos ir leksinės aplinkos, kurioje ta funkcija buvo deklaruota, derinys. Tai reiškia, kad uždaroji sritis leidžia funkcijai pasiekti kintamuosius iš ją supančios apimties srities, net ir pasibaigus išorinės funkcijos vykdymui. Galima įsivaizduoti, kad vidinė funkcija „prisimena“ savo aplinką.

Norint tai tikrai suprasti, išskaidykime pagrindinius komponentus:

Magija įvyksta todėl, kad vidinė funkcija išlaiko prieigą prie kintamųjų savo leksinėje apimties srityje, net ir po to, kai išorinė funkcija grąžina reikšmę. Šis elgesys yra esminė dalis to, kaip JavaScript tvarko apimties sritis ir atminties valdymą.

Kodėl uždarosios sritys yra svarbios?

Uždarosios sritys nėra tik teorinis konceptas; jos yra būtinos daugeliui įprastų programavimo šablonų JavaScript. Jos suteikia šiuos privalumus:

Praktiniai JavaScript uždarųjų sričių pavyzdžiai

Panagrinėkime keletą praktinių pavyzdžių, kad iliustruotume, kaip veikia uždarosios sritys ir kaip jas galima naudoti realaus pasaulio scenarijuose.

1 pavyzdys: Paprastas skaitiklis

Šis pavyzdys parodo, kaip uždaroji sritis gali būti naudojama kuriant skaitiklį, kuris išlaiko savo būseną tarp funkcijos iškvietimų.


function createCounter() {
  let count = 0;

  return function() {
    count++;
    console.log(count);
  };
}

const increment = createCounter();

increment(); // Output: 1
increment(); // Output: 2
increment(); // Output: 3

Paaiškinimas:

2 pavyzdys: Duomenų inkapsuliacija su privačiais kintamaisiais

Uždarosios sritys gali būti naudojamos kuriant privačius kintamuosius, apsaugant duomenis nuo tiesioginės prieigos ir modifikavimo iš funkcijos išorės.


function createBankAccount(initialBalance) {
  let balance = initialBalance;

  return {
    deposit: function(amount) {
      balance += amount;
      return balance; //Returning for demonstration, could be void
    },
    withdraw: function(amount) {
      if (amount <= balance) {
        balance -= amount;
        return balance; //Returning for demonstration, could be void
      } else {
        return "Insufficient funds.";
      }
    },
    getBalance: function() {
      return balance;
    }
  };
}

const account = createBankAccount(1000);

console.log(account.deposit(500)); // Output: 1500
console.log(account.withdraw(200)); // Output: 1300
console.log(account.getBalance()); // Output: 1300

// Trying to access balance directly will not work
// console.log(account.balance); // Output: undefined

Paaiškinimas:

3 pavyzdys: Uždarųjų sričių naudojimas su `setTimeout` cikle

Uždarosios sritys yra būtinos dirbant su asinchroninėmis operacijomis, tokiomis kaip setTimeout, ypač cikluose. Be uždarųjų sričių galite susidurti su netikėtu elgesiu dėl asinchroninės JavaScript prigimties.


for (var i = 1; i <= 5; i++) {
  (function(j) {
    setTimeout(function() {
      console.log("Value of i: " + j);
    }, j * 1000);
  })(i);
}

// Output:
// Value of i: 1 (after 1 second)
// Value of i: 2 (after 2 seconds)
// Value of i: 3 (after 3 seconds)
// Value of i: 4 (after 4 seconds)
// Value of i: 5 (after 5 seconds)

Paaiškinimas:

Naudojant let vietoje var cikle taip pat išspręstų šią problemą, nes let sukuria bloko apimties sritį kiekvienai iteracijai.


for (let i = 1; i <= 5; i++) {
  setTimeout(function() {
    console.log("Value of i: " + i);
  }, i * 1000);
}

// Output (same as above):
// Value of i: 1 (after 1 second)
// Value of i: 2 (after 2 seconds)
// Value of i: 3 (after 3 seconds)
// Value of i: 4 (after 4 seconds)
// Value of i: 5 (after 5 seconds)

4 pavyzdys: Karifikavimas (Currying) ir dalinis pritaikymas

Uždarosios sritys yra pagrindas karifikavimui ir daliniam pritaikymui – technikoms, naudojamoms transformuoti funkcijas su keliais argumentais į funkcijų sekas, kurių kiekviena priima vieną argumentą.


function multiply(a) {
  return function(b) {
    return function(c) {
      return a * b * c;
    };
  };
}

const multiplyBy5 = multiply(5);
const multiplyBy5And2 = multiplyBy5(2);

console.log(multiplyBy5And2(3)); // Output: 30 (5 * 2 * 3)

Paaiškinimas:

5 pavyzdys: Modulio šablonas (Module Pattern)

Uždarosios sritys plačiai naudojamos modulio šablone, kuris padeda organizuoti ir struktūrizuoti JavaScript kodą, skatinant moduliškumą ir išvengiant pavadinimų konfliktų.


const myModule = (function() {
  let privateVariable = "Hello, world!";

  function privateMethod() {
    console.log(privateVariable);
  }

  return {
    publicMethod: function() {
      privateMethod();
    },
    publicProperty: "This is a public property."
  };
})();

console.log(myModule.publicProperty); // Output: This is a public property.
myModule.publicMethod(); // Output: Hello, world!

// Trying to access privateVariable or privateMethod directly will not work
// console.log(myModule.privateVariable); // Output: undefined
// myModule.privateMethod(); // Output: TypeError: myModule.privateMethod is not a function

Paaiškinimas:

Uždarosios sritys ir atminties valdymas

Nors uždarosios sritys yra galingos, svarbu žinoti apie jų galimą poveikį atminties valdymui. Kadangi uždarosios sritys išlaiko prieigą prie kintamųjų iš jas supančios apimties srities, jos gali neleisti šiems kintamiesiems būti surinktiems šiukšlių surinkėjo (garbage collector), jei jie nebėra reikalingi. Tai gali sukelti atminties nutekėjimą, jei su tuo elgiamasi neatsargiai.

Kad išvengtumėte atminties nutekėjimo, užtikrinkite, kad nutrauktumėte visas nereikalingas nuorodas į kintamuosius uždarosiose srityse, kai jos nebėra reikalingos. Tai galima padaryti nustatant kintamųjų reikšmę į null arba pertvarkant kodą, kad išvengtumėte nereikalingų uždarųjų sričių kūrimo.

Dažniausios klaidos su uždarosiomis sritimis, kurių reikia vengti

Išvada

JavaScript uždarosios sritys yra galingas ir esminis konceptas, kurį turi suprasti kiekvienas JavaScript programuotojas. Jos įgalina duomenų inkapsuliaciją, būsenos išsaugojimą, aukštesnės eilės funkcijas ir asinchroninį programavimą. Suprasdami, kaip veikia uždarosios sritys ir kaip jas efektyviai naudoti, galite rašyti efektyvesnį, prižiūrimą ir saugesnį kodą.

Šiame vadove pateikta išsami uždarųjų sričių apžvalga su praktiniais pavyzdžiais. Praktikuodamiesi ir eksperimentuodami su šiais pavyzdžiais, galite pagilinti savo supratimą apie uždarąsias sritis ir tapti labiau patyrusiu JavaScript programuotoju.

Tolimesniam mokymuisi