Men hech qachon JavaScript yopilishini tushunmadim

Kimdir buni menga shunday tushuntirmaguncha ...

Sarlavhada aytilganidek, JavaScript yopilishi men uchun doim ham sir bo'lib kelgan. Men bir nechta maqolalarni o'qib chiqdim, ishimda yopilishlardan foydalandim, ba'zida hatto yopilishni ishlatganligimni bilmasdan ham yopishdan foydalandim.

Yaqinda men nutqqa bordim, u erda kimdir uni nihoyat men uchun bosgan tarzda tushuntirdi. Ushbu maqoladagi yopilishlarni tushuntirish uchun ushbu usulni qo'llashga harakat qilaman. CodeSmith va ularning JavaScript-larining "Qattiq qismlar" seriyasidagi buyuk odamlarga maqtovlar bildirishga ijozat bering.

Biz boshlashdan oldin

Ba'zi tushunchalar, yopilishni boshlashdan oldin, o'zingizni tutish uchun muhimdir. Ulardan biri ijro etilish kontekstidir.

Ushbu maqola Amalga oshirish kontekstida juda yaxshi qo'llanmaga ega. Maqoladan iqtibos keltiring:

Kod JavaScript-da ishlaganda, uni amalga oshiradigan muhit juda muhim va quyidagilardan biri sifatida baholanadi:
Global kod - Sizning kodingiz birinchi marta bajariladigan standart muhit.
Funktsiya kodi - har doim bajarilish oqimi funktsiya tanasiga kirganda.
(…)
(...), hozirgi kodni ko'rib chiqayotgan muhit / maydonni ko'rib chiqish muddatini bajarish kontekstini o'ylab ko'raylik.

Boshqacha qilib aytganda, biz dasturni ishga tushirganimiz sari global ijro etilish kontekstida boshlaymiz. Ba'zi o'zgaruvchilar global ijro etish kontekstida e'lon qilinadi. Biz bu global o'zgaruvchilar deb ataymiz. Dastur funktsiyani chaqirganda, nima sodir bo'ladi? Bir necha qadam:

  1. JavaScript yangi ijro etuvchi kontekstni, mahalliy ijro kontekstini yaratadi
  2. Ushbu mahalliy ijro kontekstida o'z parametrlari to'plamiga ega bo'ladi, bu o'zgaruvchilar ushbu ijro kontekstiga nisbatan mahalliy bo'ladi.
  3. Ijroning yangi konteksti ijro stekiga tashlanadi. Dastur qayerda bajarilishini kuzatib borish mexanizmi sifatida ijro stekini o'ylab ko'ring

Funktsiya qachon tugaydi? Qaytish bayonotiga duch kelganda yoki yopilish qavsiga duch kelganda}. Funktsiya tugaganda, quyidagilar sodir bo'ladi:

  1. Mahalliy ijro kontekstlari ijro stekida paydo bo'ladi
  2. Vazifalar qaytariladigan qiymatni chaqirilayotgan kontekstga qaytaradi. Chaqiriladigan kontekst bu funktsiyani chaqiradigan ijro etuvchi kontekst, global ijro etilish konteksti yoki boshqa mahalliy ijro etilish konteksti bo'lishi mumkin. O'sha paytda qaytish qiymati bilan shug'ullanish chaqiruvni bajarish kontekstiga bog'liq. Qaytarilgan qiymat ob'ekt, qator, funktsiya, mantiqiy narsa bo'lishi mumkin. Agar funktsiya qaytish bayonotiga ega bo'lmasa, aniqlanmagan qiymat qaytariladi.
  3. Mahalliy ijro konteksti yo'q qilingan. Bu juda muhim. Vayron qilingan. Mahalliy ijro kontekstida e'lon qilingan barcha o'zgaruvchilar o'chiriladi. Ular endi mavjud emas. Shuning uchun ular mahalliy o'zgaruvchilar deb nomlanadi.

Juda asosiy misol

Yopilishdan oldin, quyidagi kodni ko'rib chiqaylik. Bu juda sodda ko'rinadi, ehtimol ushbu maqolani o'qigan har bir kishi nima qilayotganini aniq biladi.

1: a = 3 bo'lsin
2: funktsiya addTwo (x) {
3: ret = x + 2 ga ruxsat bering
4: orqaga qaytish
5:}
6: ruxsat b = addTwo (a)
7: konsol.log (b)

JavaScript mexanizmi qanday ishlashini tushunish uchun uni batafsil ko'rib chiqaylik.

  1. 1-satrda biz global o'zgaruvchan kontekstda yangi o'zgaruvchini e'lon qilamiz va unga 3 raqamini beramiz.
  2. Keyinchalik qiyin bo'ladi. 2 dan 5 gacha chiziqlar, albatta, birga. Bu erda nima bo'ladi? Global bajarish kontekstida addTwo nomli yangi o'zgaruvchini e'lon qilamiz. Va biz unga nimani tayinlaymiz? Funktsiya ta'rifi. Ikki qavs orasida nima bo'lsa ham,} addTwo tayinlangan. Funktsiya ichidagi kod baholanmaydi, bajarilmaydi, kelajakda foydalanish uchun faqat o'zgaruvchiga saqlanadi.
  3. Shunday qilib, biz 6-qatorga kirmoqdamiz. Bu juda oddiy ko'rinadi, ammo bu erda ochish uchun juda ko'p narsa bor. Avval biz global o'zgaruvchan kontekstda yangi o'zgaruvchini e'lon qilamiz va uni b deb belgilaymiz. O'zgaruvchini e'lon qilish bilanoq u aniqlanmagan qiymatga ega bo'ladi.
  4. Keyingi, 6-qatorda, biz tayinlash operatorini ko'ramiz. B o'zgaruvchisiga yangi qiymat tayinlashga tayyorlanmoqdamiz. Keyinchalik biz chaqirilayotgan funktsiyani ko'ramiz. O'zgaruvchini va uning ichida yumaloq qavslar bilan (...) ko'rsangiz, bu funktsiya chaqirilayotganligidan dalolat beradi. Oldinga siljiting, har bir funktsiya biror narsani qaytaradi (qiymat, ob'ekt yoki aniqlanmagan). Funktsiyadan qaytarilgan narsa b o'zgaruvchisiga beriladi.
  5. Lekin avval biz addTwo deb belgilangan funktsiyani chaqirishimiz kerak. JavaScript borib, addTwo nomli o'zgaruvchiga global bajariladigan kontekst xotirasini ko'radi. Oh, bittasini topdi, u 2-bosqichda (yoki 2-5 chiziqlar) aniqlandi. Va loB va ko'rilayotgan o'zgaruvchi addTwo funksiya ta'rifini o'z ichiga oladi. E'tibor bering, a o'zgaruvchisi funktsiya uchun argument sifatida uzatiladi. JavaScript o'zgaruvchini global bajariladigan kontekst xotirasida qidiradi, uni topadi, uning qiymati 3 ekanligini topadi va 3 raqamini funktsiyaga argument sifatida uzatadi. Funktsiyani bajarishga tayyor.
  6. Endi ijro konteksti o'zgaradi. Mahalliy ijro etilishning yangi konteksti yaratildi. Bajarish konteksti qo'ng'iroqlar to'plamiga suriladi. Mahalliy ijroiya kontekstida birinchi navbatda nima qilamiz?
  7. Sizda: "O'zgarishlarning yangi versiyasi mahalliy ijro etiladigan kontekstda e'lon qilindi", - deb aytishingiz mumkin. Bu javob emas. To'g'ri javob, avval funktsiyaning parametrlarini ko'rib chiqishimiz kerak. Yangi o'zgaruvchi x mahalliy ijrosi kontekstida e'lon qilinadi. Va 3 qiymati argument sifatida qabul qilinganligi sababli, x o'zgaruvchiga 3 raqami beriladi.
  8. Keyingi qadam: yangi o'zgaruvchi ret mahalliy ijro sharoitida e'lon qilinadi. Uning qiymati aniqlanmagan qilib o'rnatiladi. (3-qator)
  9. Hali ham 3-qatorda qo'shimcha qilish kerak. Avval x qiymatiga muhtojmiz. JavaScript o'zgaruvchini qidiradi. Bu avval mahalliy ijro etilish kontekstida ko'rinadi. Va bitta topildi, qiymati - 3 va ikkinchi operand - bu 2 raqami. Qo'shish natijasi (5) ret o'zgaruvchisiga beriladi.
  10. 4-qator. Biz o'zgaruvchining ret tarkibini qaytaramiz. Mahalliy ijro kontekstida yana bir qidiruv. ret 5 qiymatini o'z ichiga oladi. funktsiya 5 raqamini qaytaradi va funktsiya tugaydi.
  11. 4-5 qatorlar. Funktsiya tugaydi. Mahalliy ijro konteksti yo'q qilingan. X va ret o'zgaruvchilar yo'q qilinadi. Ular endi yo'q. Kontekst qo'ng'iroqlar to'plamida ochiladi va qaytish qiymati qo'ng'iroq kontekstiga qaytariladi. Bu holda chaqirilayotgan kontekst global ijro kontekstidir, chunki addTwo funktsiyasi global ijro etilish kontekstidan chaqirildi.
  12. Endi biz 4-bosqichda qoldirgan joyimizni olamiz. Qaytarilgan qiymat (5 raqami) b o'zgaruvchisiga beriladi. Biz kichkina dasturning 6-qatorida turibmiz.
  13. Men batafsil ma'lumot bermayman, lekin 7-satrda b o'zgaruvchisining tarkibi konsolda chop etiladi. Bizning misolimizda 5 raqami.

Bu juda oddiy dastur uchun juda uzoq davom etgan tushuntirish edi va biz hozircha yopilishlar haqida ham gapirmadik. Va'da beraman, biz u erga etib boramiz. Ammo oldin yana bitta yoki ikkita aylanma yo'lni tanlashimiz kerak.

Leksik doirasi.

Leksik doiraning ba'zi jihatlarini tushunishimiz kerak. Quyidagi misolni ko'rib chiqing.

1: bo'lsin val1 = 2
2: funktsiya multiplyThis (n) {
3: let = n * val1 bo'lsin
4: orqaga qaytish
5:}
6: ko'paytirilsin = ko'paytirilsin (6)
7: console.log ('qamrov namunasi:', ko'paytirilgan)

Bu erda g'oya shundan iboratki, bizda mahalliy ijro kontekstida va global ijro etilish kontekstida o'zgaruvchilar mavjud. Javoblarning eng qiziq tomoni shundaki, u o'zgaruvchini izlash usulidir. Agar u mahalliy ijro etilish kontekstida o'zgaruvchini topa olmasa, uni chaqiradigan kontekstida qidiradi. Va agar uning chaqiruv kontekstida u erda topilmasa. Qayta-qayta, global ijro etilish kontekstida izlangunga qadar. (Agar u u erda topilmasa, aniqlanmagan). Yuqoridagi misol bilan birga amal qiling, bu aniqlik kiritadi. Agar ko'lam qanday ishlashini tushunsangiz, buni o'tkazib yuborishingiz mumkin.

  1. Global o'zgaruvchan kontekstda yangi o'zgaruvchini val1 deb e'lon qiling va unga 2 raqamini bering.
  2. 2–5 qatorlar. Yangi o'zgaruvchini multiplikThis deb e'lon qiling va unga funktsiya ta'rifini bering.
  3. 6-qator. Global o'zgaruvchan kontekstda ko'paytiriladigan yangi o'zgaruvchini e'lon qiling.
  4. O'zgaruvchini multiplyThis global global kontekst xotirasidan oling va uni funktsiya sifatida bajaring. 6 raqamini dalil sifatida bering.
  5. Yangi funktsiya qo'ng'iroq = yangi ijro kontekst. Mahalliy ijro kontekstini yarating.
  6. Mahalliy ijroiya kontekstida n o'zgaruvchini e'lon qiling va unga 6 raqamini bering.
  7. 3-qator. Mahalliy ijroiya kontekstida o'zgaruvchini e'lon qiling.
  8. 3-qator (davomi). Ikki operand bilan ko'payishni bajaring; n va val1 o'zgaruvchilarning tarkibi. Mahalliy ijrochilik kontekstida n o'zgaruvchini qidirib toping. Biz buni 6-bosqichda e'lon qildik. Uning mazmuni 6-raqam. Mahalliy ijrochilik kontekstida val1 o'zgaruvchisini qidirib toping. Mahalliy ijrochilik kontekstida val1 o'zgarmaydigan markasi mavjud emas. Qo'ng'iroq kontekstini tekshirib ko'raylik. Chaqiruvchi kontekst bu global ijro etuvchi kontekst. Global ijro etilish kontekstida val1-ni qidiraylik. Ha, o'sha erda. U 1-bosqichda aniqlandi. Qiymat 2 raqami.
  9. 3-qator (davomi). Ikkala operandani ko'paytiring va uni ret o'zgaruvchisiga tayinlang. 6 * 2 = 12. ret endi 12 ga teng.
  10. Ret o'zgaruvchini qaytaring. Mahalliy ijrochilik konteksti va n va uning o'zgaruvchilari bilan birga yo'q qilinadi. O'zgaruvchan val1 yo'q qilinmaydi, chunki u global ijro etilish kontekstining bir qismi edi.
  11. 6-qatorga qayting. Chaqirilayotgan kontekstda 12 raqami ko'paytiriladigan o'zgaruvchiga tayinlanadi.
  12. Va nihoyat, 7-qatorda biz konsolda ko'paytirilgan o'zgaruvchining qiymatini ko'rsatamiz.

Shunday qilib, ushbu misolda, funktsiya chaqiruvchi kontekstida aniqlanadigan parametrlarga kirish huquqiga ega ekanligini esga olishimiz kerak. Ushbu hodisaning rasmiy nomi leksik doiradir.

Funktsiyani qaytaradigan funksiya

Birinchi misolda addTwo funktsiyasi raqamni qaytaradi. Funktsiya har qanday narsani qaytarishi mumkinligini avvalgidan eslang. Funktsiyani qaytaradigan funktsiyaning misolini ko'rib chiqaylik, chunki bu yopilishlarni tushunish uchun zarurdir. Mana biz tahlil qilmoqchi bo'lgan misol.

 1: let val = 7
 2: createAdder () funktsiyasi
 3: addNearn (a, b) funktsiyasi {
 4: ruxsat = a + b
 5: orqaga qaytish
 6:}
 7: return addNearn
 8:}
 9: let adder = createAdder ()
10: sum sum = qo'shing (val, 8)
11: console.log ('funktsiyani qaytaradigan funktsiya namunasi:', sum)

Bosqichma-bosqich bo'linishga qaytaylik.

  1. 1-qator. Biz o'zgarmaydigan valni global bajarilish kontekstida e'lon qilamiz va shu o'zgaruvchiga 7 raqamini beramiz.
  2. 2–8 qatorlar. Umumjahon ijroiya kontekstida biz yaratuvchini yaratuvchisi deb nomlaymiz va unga funktsiya ta'rifini beramiz. 3 dan 7 gacha qatorlar ushbu funktsiyaning ta'rifini tavsiflaydi. Avvalgidek, hozirda, biz bu funktsiyaga sakramayapmiz. Biz shunchaki funktsiya ta'rifini o'sha o'zgaruvchiga saqlaymiz (createAdder).
  3. 9-qator. Biz global ijro etish kontekstida yangi o'zgaruvchini e'lon qiluvchini e'lon qilamiz. Vaqtincha, aniqlanmagan narsa qo'shimchaga tayinlanadi.
  4. Hali chiziq 9. Biz qavslarni ko'ramiz (); funktsiyani bajarish yoki chaqirish kerak. Ijro etishning global kontekstini xotirasini so'rab, createAdder nomli o'zgaruvchini qidiraylik. U 2-bosqichda yaratilgan. Mayli, chaqiraylik.
  5. Funktsiyani chaqirish. Endi biz 2-qatorga o'tmoqdamiz. Yangi ijro etiladigan mahalliy kontekst yaratildi. Yangi ijro kontekstida lokal o'zgaruvchilarni yaratishimiz mumkin. Dvigatel qo'ng'iroq stekiga yangi kontekstni qo'shadi. Funktsiyada hech qanday dalillar yo'q, keling uning tanasiga o'taylik.
  6. Hali ham 3-6 chiziqlar. Bizda yangi funksiya deklaratsiyasi mavjud. Mahalliy ijro etiladigan kontekstda addNordamlar o'zgaruvchisini yaratamiz. Bu muhim. addNumbers faqat mahalliy ijro etiladigan kontekstda mavjud. Funktsiya ta'rifini addNumbers nomli mahalliy o'zgaruvchiga saqlaymiz.
  7. Endi biz 7-qatorga kirmoqdamiz addNumber o'zgaruvchisining tarkibini qaytaramiz. Dvigatel addNumbers nomli o'zgaruvchini qidiradi va uni topadi. Bu funktsiya ta'rifi. Yaxshi, funktsiya har qanday narsani qaytarishi mumkin, shu jumladan funktsiya ta'rifi. Shunday qilib, biz addNumbers ta'rifini qaytaramiz. 4 va 5-qatorlardagi qavslar orasidagi har qanday narsa funktsiyaning ta'rifini tashkil qiladi. Shuningdek, biz mahalliy ijro etilish kontekstini qo'ng'iroq stekidan o'chiramiz.
  8. Qaytgandan so'ng, mahalliy ijro konteksti yo'q qilinadi. AddNumbers o'zgaruvchisi yo'q. Funktsiya ta'rifi hanuzgacha mavjud, ammo u funktsiyadan qaytariladi va u o'zgaruvchan qo'shimchaga beriladi; bu biz 3 bosqichda yaratgan o'zgaruvchidir.
  9. Endi biz 10-qatorga kirmoqdamiz. Biz global o'zgaruvchan kontekstda yangi o'zgaruvchan summani aniqlaymiz. Vaqtinchalik tayinlash aniqlanmagan.
  10. Keyingi funktsiyani bajarishimiz kerak. Qaysi funktsiya? Adder deb nomlangan o'zgaruvchida aniqlanadigan funktsiya. Biz uni global ijro etilish kontekstida ko'rib chiqamiz va biz uni aniq topamiz. Bu ikkita parametrni o'z ichiga oladigan funktsiya.
  11. Keling, ikkita parametrni olaylik, shuning uchun funktsiyani chaqirib, to'g'ri dalillarni olamiz. Birinchisi, biz 1-bosqichda aniqlagan o'zgaruvchan val, u 7 raqamini, ikkinchisi - 8 raqamini anglatadi.
  12. Endi biz ushbu funktsiyani bajarishimiz kerak. Funktsiya ta'rifi 3-5 chiziqlarida keltirilgan. Mahalliy ijroning yangi konteksti yaratildi. Mahalliy kontekstda ikkita yangi o'zgaruvchilar yaratiladi: a va b. Ularga mos ravishda 7 va 8 qiymatlari beriladi, chunki biz oldingi bosqichda funktsiyaga o'tgan dalillar edi.
  13. 4-qator. Yangi deb nomlangan, o'zgaruvchiga ret deb nom berilgan. Bu mahalliy ijro etuvchi kontekstda e'lon qilingan.
  14. 4-qator. Qo'shimcha amalga oshiriladi, bunda biz a o'zgaruvchisi va b o'zgaruvchisi tarkibini qo'shamiz. Qo'shish natijasi (15) ret o'zgaruvchisiga beriladi.
  15. Ret o'zgaruvchisi ushbu funktsiyadan qaytariladi. Mahalliy ijro konteksti yo'q qilingan, u qo'ng'iroq stekidan o'chirildi, a, b va ret parametrlari endi mavjud emas.
  16. Qaytarilgan qiymat, biz 9-qadamda aniqlagan summa o'zgaruvchisiga tayinlanadi.
  17. Biz konsolga summaning qiymatini chiqaramiz.

Kutilganidek, konsol 15 ni bosib chiqaradi. Biz bu erda bir nechta halqa bilan o'tamiz. Men bu erda bir nechta fikrlarni tasvirlashga harakat qilaman. Birinchidan, funktsiya ta'rifi o'zgaruvchida saqlanishi mumkin, funktsiya ta'rifi dastur chaqirilmaguncha ko'rinmaydi. Ikkinchidan, har safar biron bir funktsiya chaqirilganda, mahalliy ijro konteksti (vaqtincha) yaratiladi. Funktsiya bajarilgandan so'ng ushbu ijro konteksti yo'qoladi. Funktsiya qaytish yoki yopilish qavsiga duch kelganda bajariladi}.

Va nihoyat, yopilish

Keyingi kodni ko'rib chiqing va nima bo'lishini aniqlashga harakat qiling.

 1: funktsiya createCounter () {
 2: hisoblagich = 0 ga teng
 3: const myFunction = funktsiya () {
 4: hisoblagich = hisoblagich + 1
 5: qaytib hisoblagich
 6:}
 7: qaytish myFunction
 8:}
 9: const increment = createCounter ()
10: const c1 = o'sish ()
11: const c2 = o'sish ()
12: const c3 = o'sish ()
13: console.log ('namunaviy o'sish', c1, c2, c3)

Endi biz oldingi ikkita misoldan shuni bilib oldik, buni bajarilishini kutib o'tiraylik.

  1. 1–8 qatorlar. Biz global o'zgaruvchan kontekstda createCounter yangi o'zgaruvchini yaratamiz va unga vazifa ta'rifi beriladi.
  2. 9-qator. Biz global ijro etish kontekstida nomlangan yangi o'zgaruvchini e'lon qilamiz ..
  3. 9-qator yana. Bizga createCounter funktsiyasini chaqirish va qaytarilgan qiymatni qo'shimcha o'zgaruvchiga tayinlash kerak.
  4. 1–8 qatorlar. Funktsiyani chaqirish. Mahalliy ijroning yangi kontekstini yaratish.
  5. 2-qator. Mahalliy ijroiya kontekstida hisoblagich deb nomlangan yangi o'zgaruvchini e'lon qiling. 0 raqami hisoblagichga tayinlangan.
  6. 3-6 qator. MyFunction nomli yangi o'zgaruvchini e'lon qilish. O'zgaruvchi mahalliy ijro etiladigan kontekstda e'lon qilinadi. O'zgaruvchining tarkibi yana bir funktsiya ta'rifidir. 4 va 5-qatorlarda belgilanganidek.
  7. 7-qator. MyFunction o'zgaruvchisining tarkibini qaytarish. Mahalliy ijrochilik konteksti o'chirildi. myFunction va hisoblagich endi mavjud emas. Tekshirish qo'ng'iroq kontekstiga qaytariladi.
  8. Chiziq 9. Chaqiriladigan kontekstda, global bajarish kontekstida, createCounter tomonidan qaytarilgan qiymat o'sishga tayinlangan. O'zgaruvchan o'sish hozirda funktsiyani aniqlashni o'z ichiga oladi. CreateCounter tomonidan qaytarilgan funktsiya ta'rifi. Endi u MyFunction deb nomlanmagan, ammo u xuddi shu ta'rif. Umumjahon kontekstida bu "etiketlash" deb nomlanadi.
  9. 10-qator. Yangi o'zgaruvchini e'lon qiling (c1).
  10. 10-qator (davomi). O'zgaruvchan o'zgarishni qidirib toping, bu funktsiya, uni chaqiring. U 4-5 satrlarda belgilanganidek ilgari berilgan funktsiyalarni o'z ichiga oladi.
  11. Ijroning yangi kontekstini yarating. Parametrlar yo'q. Funktsiyani bajarishni boshlang.
  12. 4-qator. Hisoblagich = hisoblagich +. Biz shunchaki ushbu kontekstni yaratdik va hech qachon mahalliy o'zgaruvchilar haqida e'lon qilmaymiz. Ijro etishning global kontekstida ko'rib chiqaylik. Bu erda o'zgaruvchan yorliqli hisoblagich yo'q. Javascript buni counter = undefined + 1 deb baholaydi, yangi mahalliy o'zgaruvchan yorliqli hisoblagichni e'lon qiladi va aniqlanmagan 0 kabi, unga 1 raqamini beradi.
  13. 5-qator. Hisoblagichning mazmunini yoki 1-sonni qaytaramiz. Biz mahalliy ijro kontekstini va hisoblagich o'zgaruvchisini yo'q qilamiz.
  14. 10 qatorga qayting. Qaytarilgan qiymat (1) c1 ga beriladi.
  15. 11-qator. Biz 10-14 bosqichlarni takrorlaymiz, c2 ham 1 ga beriladi.
  16. 12-qator. Biz 10-14 bosqichlarni takrorlaymiz, c3 ham 1 ga beriladi.
  17. 13-qator. Biz c1, c2 va c3 o'zgaruvchilar tarkibiga kiramiz.

Buni o'zingiz uchun sinab ko'ring va nima bo'lishini ko'ring. Siz yuqorida tushuntirganimdan kutish mumkin bo'lganidek, 1, 1 va 1 yozuvlari qayd qilinmayotganini ko'rasiz. Buning o'rniga u 1, 2 va 3 jurnallarni ro'yxatga oladi. Xo'sh, nima beradi?

Qanday bo'lmasin, o'sish funktsiyasi ushbu hisoblagich qiymatini eslab qoladi. Bu qanday ishlaydi?

Hisoblagich global ijro etilish kontekstining qismimi? Console.log (counter) -ni sinab ko'ring va siz aniqlanmaysiz. Shunday qilib, bu shunday emas.

Ehtimol, siz qo'shimcha qo'ng'iroq qilsangiz, u qandaydir tarzda u yaratilgan funktsiyaga qaytadi (createCounter)? Bu qanday ishlaydi? O'zgaruvchan o'sish funktsiyasi ta'rifini o'z ichiga oladi, u qaerdan kelganligini emas. Shunday qilib, bu shunday emas.

Shunday qilib, boshqa mexanizm bo'lishi kerak. Yopilish. Biz nihoyat, etishmayotgan qismga etib keldik.

Mana bu qanday ishlaydi. Siz har doim yangi funktsiyani e'lon qilib, uni o'zgaruvchiga tayinlaganingizda, siz funktsiyaning ta'rifini, shuningdek yopilishini saqlaysiz. Yopish funktsiyani yaratish vaqtida mavjud bo'lgan barcha o'zgaruvchilarni o'z ichiga oladi. Bu xalta bilan o'xshashdir. Funktsiya ta'rifi ozgina xalta bilan birga keladi. Va uning to'plamida funktsiyani aniqlash vaqtida yaroqli bo'lgan barcha o'zgaruvchilar saqlanadi.

Shunday qilib, yuqorida bizning tushuntirishimiz noto'g'ri edi, yana urinib ko'raylik, lekin bu safar to'g'ri.

1: funktsiya createCounter () {
 2: hisoblagich = 0 ga teng
 3: const myFunction = funktsiya () {
 4: hisoblagich = hisoblagich + 1
 5: qaytib hisoblagich
 6:}
 7: qaytish myFunction
 8:}
 9: const increment = createCounter ()
10: const c1 = o'sish ()
11: const c2 = o'sish ()
12: const c3 = o'sish ()
13: console.log ('namunaviy o'sish', c1, c2, c3)
  1. 1–8 qatorlar. Biz global o'zgaruvchan kontekstda createCounter yangi o'zgaruvchini yaratamiz va unga vazifa ta'rifi beriladi. Yuqoridagi kabi.
  2. 9-qator. Biz global ijro etish kontekstida yangi o'zgaruvchi deb nomlangan e'lon qilamiz. Yuqoridagi kabi.
  3. 9-qator yana. Bizga createCounter funktsiyasini chaqirish va qaytarilgan qiymatni qo'shimcha o'zgaruvchiga tayinlash kerak. Yuqoridagi kabi.
  4. 1–8 qatorlar. Funktsiyani chaqirish. Mahalliy ijroning yangi kontekstini yaratish. Yuqoridagi kabi.
  5. 2-qator. Mahalliy ijroiya kontekstida hisoblagich deb nomlangan yangi o'zgaruvchini e'lon qiling. 0 raqami hisoblagichga tayinlangan. Yuqoridagi kabi.
  6. 3-6 qator. MyFunction nomli yangi o'zgaruvchini e'lon qilish. O'zgaruvchi mahalliy ijro etiladigan kontekstda e'lon qilinadi. O'zgaruvchining tarkibi yana bir funktsiya ta'rifidir. 4 va 5-satrlarda belgilanganidek, endi biz yopilishni yaratamiz va uni funktsiyani aniqlashning bir qismi sifatida qo'shamiz. Yopish tarkibiga kiradigan o'zgaruvchilar mavjud, bu holda o'zgaruvchan hisoblagich (0 bilan).
  7. 7-qator. MyFunction o'zgaruvchisining tarkibini qaytarish. Mahalliy ijrochilik konteksti o'chirildi. myFunction va hisoblagich endi mavjud emas. Tekshirish qo'ng'iroq kontekstiga qaytariladi. Shunday qilib, biz funktsiya ta'rifi va uning yopilishi, uni yaratishda foydalanilgan o'zgaruvchilar bilan orqa ruchkani qaytaramiz.
  8. Chiziq 9. Chaqiriladigan kontekstda, global bajarish kontekstida, createCounter tomonidan qaytarilgan qiymat o'sishga tayinlangan. O'zgaruvchan o'sish hozirda funktsiyaning ta'rifini o'z ichiga oladi (va yopish). CreateCounter tomonidan qaytarilgan funktsiya ta'rifi. Endi u MyFunction deb nomlanmagan, ammo u xuddi shu ta'rif. Umumjahon kontekstda bu o'sish deyiladi.
  9. 10-qator. Yangi o'zgaruvchini e'lon qiling (c1).
  10. 10-qator (davomi). O'zgaruvchan o'zgarishni qidirib toping, bu funktsiya, uni chaqiring. U 4-5 satrlarda belgilanganidek ilgari berilgan funktsiyalarni o'z ichiga oladi. (va shuningdek, o'zgaruvchilar bilan bir xalta bor)
  11. Ijroning yangi kontekstini yarating. Parametrlar yo'q. Funktsiyani bajarishni boshlang.
  12. 4-qator. Hisoblagich = hisoblagich + 1. O'zgaruvchan hisoblagichni qidirishimiz kerak. Mahalliy yoki global ijro etilish kontekstiga qarashdan oldin, bizning ryukzakimizni ko'rib chiqaylik. Yopilishini tekshirib ko'raylik. Mana va qarang, yopilish deb nomlangan hisoblagich o'z ichiga oladi, uning qiymati 0. 4-qatorda ifodadan keyin uning qiymati 1-ga o'rnatiladi va u yana xalta ichida saqlanadi. Endi yopilish qiymati 1 ga teng bo'lgan o'zgaruvchan hisoblagich mavjud.
  13. 5-qator. Hisoblagichning mazmunini yoki 1-sonni qaytaramiz. Biz mahalliy ijro kontekstini yo'q qilamiz.
  14. 10 qatorga qayting. Qaytarilgan qiymat (1) c1 ga beriladi.
  15. 11-qator. Biz 10-14 bosqichlarni takrorlaymiz. Bu safar biz yopilishimizga qaraganimizda, hisoblagich o'zgaruvchisi 1 ga teng qiymatga ega ekanligini ko'ramiz, bu dasturning 12-bosqichida yoki 4-qatorda o'rnatildi. Uning qiymati o'sish funktsiyasining yopilishida 2 sifatida saqlanib qoladi. Va c2 ga 2 beriladi.
  16. 12-qator. Biz 10-14 bosqichlarni takrorlaymiz, c3 3 ga beriladi.
  17. 13-qator. Biz c1, c2 va c3 o'zgaruvchilar tarkibiga kiramiz.

Shunday qilib, endi biz bu qanday ishlashini tushunamiz. Esda tutish kerak bo'lgan narsa shundan iboratki, biror funktsiya e'lon qilinganida, u funktsiyaning ta'rifi va yopilishini o'z ichiga oladi. Yopish - bu funktsiyani yaratish vaqtidagi barcha o'zgaruvchilar yig'indisi.

Siz so'rashingiz mumkin, biron bir funktsiyaning yopilishi, hatto global miqyosda yaratilgan funktsiyalari bormi? Javob: ha. Global miqyosda yaratilgan funktsiyalar yopilishni keltirib chiqaradi. Ammo bu funktsiyalar global miqyosda yaratilganligi sababli ular global miqyosdagi barcha o'zgaruvchilarga kirish huquqiga ega. Va yopilish kontseptsiyasi haqiqatan ham tegishli emas.

Funktsiya funktsiyani qaytarganda, ya'ni yopilish tushunchasi yanada muhimroq bo'ladi. Qaytarilgan funktsiya global miqyosda bo'lmagan o'zgaruvchiga kirish huquqiga ega, ammo ular faqat uning yopilishida mavjud.

Emas, balki ahamiyatsiz yopilish

Ba'zida yopilishlar siz hatto sezmaganingizda ham paydo bo'ladi. Ehtimol, biz qisman dastur deb nomlangan misolni ko'rgan bo'lishingiz mumkin. Quyidagi kod kabi.

ruxsat bering c = 4
const addX = x => n => n + x
const addThree = addX (3)
d = qo'shingTesh (s) ga
console.log ('qisman dastur namunasi', d)

Agar o'q vazifasi sizni tashlasa, bu erda ekvivalent bo'ladi.

ruxsat bering c = 4
funktsiya addX (x) {
  qaytish funktsiyasi (n) {
     n + x ni qaytaring
  }
}
const addThree = addX (3)
d = qo'shingTesh (s) ga
console.log ('qisman dastur namunasi', d)

Biz bitta parametrni (x) oladigan va boshqa funktsiyani qaytaradigan addX funktsiyasini e'lon qilamiz.

Qaytarilgan funktsiya bitta parametrni oladi va uni x o'zgaruvchisiga qo'shadi.

O'zgaruvchi x yopilish qismidir. AddThree o'zgaruvchisi mahalliy kontekstda e'lon qilinganida, unga funktsiyalarni aniqlash va yopish vazifasi yuklanadi. Yopish x o'zgaruvchini o'z ichiga oladi.

Endi addThree chaqirilganda va bajarilganda x o'zgaruvchisiga va argument sifatida uzatiladigan n o'zgaruvchiga kirish imkoniyati mavjud.

Ushbu misolda konsol 7 raqamini chiqaradi.

Xulosa

Yopilishlarni har doim eslab qolishim - bu xalta o'xshashligi. Agar funktsiya yaratilsa va uning atrofiga topshirilsa yoki boshqa funktsiyadan qaytib kelsa, u o'zi bilan xalta olib yuradi. Va xalta ichida funktsiyani e'lon qilish paytida barcha o'zgaruvchilar mavjud.

Agar siz buni o'qishni yoqtirsangiz, qarsaklaringizni unutmang.
Rahmat.