Затварянето е комбинация от функция и лексикалната среда, в която тази функция е декларирана като ¹.

какво стана там

Ако вие, като много други, смятате, че ред 12 ще върне 3, тогава тази статия може да ви помогне малко. Това, което се случва, е, че всеки път, когато извикаме count(), връщаме ново копие на функцията innerCount и всяко копие на innerCount разчита на данни, които са извън себе си, извън своя собствен обхват.

Тези данни за средата, както можете да ги наречете, са от решаващо значение за изпълнението на самата функция. Можем да кажем, че зависи от това да работи. Ако, когато стартираме innerCount, нямаме достъп до counter, тогава цялата функция ще бъде повредена! Но докато innerCount се изпълни, counter вече не е достъпен за външния свят!

JavaScript идва на помощ и той обвива, групира или, ако искате да го кажете правилно, създава затваряне около функцията и всички данни, до които трябва да има достъп, нейната лексикална среда.

Ако counter беше променлива в глобалния обхват, тогава всички броячи ще увеличават една и съща променлива вместо една вътре в затваряне. Чувствайте се свободни да го изпробвате, като извлечете counter до горния ред 1

Създаване на функционална фабрика като пример от реалния свят

Можем да се възползваме от поведението на затваряне, като създадем функция, която в зависимост от предадените аргументи връща функция с различна логика на изпълнение. Най-простият пример, за който се сещам, е фабрика, която ще върне степента на n за дадено число. Резултатът ще бъде същият като при извикване на Math.pow(subject, power)

Това, което прави този фрагмент, е да създаде динамична функция, по същество функция, чийто алгоритъм не е изрично дефиниран в самия код, а по-скоро по време на изпълнение, когато е създаден с аргументите, предадени на фабриката. Разбира се, с предишния пример може да си помислите, че е доста безполезен и ще сте прави, но това, което трябва да разберете, е потенциалът, който има тази функционалност.

Вече можем да дефинираме функция, която ни дава силата на две, като просто извикаме var powerOf2 = powerOfNFactory(2). Вътрешният generatedFunction ще запази затваряне над променливата power и ще бъде напълно независим от други извиквания към powerOfNFactory. Това означава, че можем да разширим функционалността и да правим неща като следене на броя пъти, когато нашата динамична функция е била извикана, добавяне на мемоизация(кеширане на резултатите, за да се предотврати повторно изпълнение при извикване със същите аргументи) и много повече.

Добавяне на брояча

По същия начин, по който нашата динамична функция има достъп до аргумента, предаден на фабричната функция, тя ще има достъп до всичко, дефинирано вътре в нея, точно както в първия пример с брояча, което ни позволява да дефинираме прост брояч и по този начин да следим от времето, когато сме наричали това. Може би бихте искали да направите това за целите на регистриране, може би бихте искали да ограничите броя пъти, когато дадена функционалност може да бъде изпълнена, преди да направите нещо друго, зависи от вас.

Мемоизация

Тъй като кодът, изпълняван в нашата функция, не е скъп от гледна точка на време, не трябва да се тревожим за кеширането на изпълнението му, но е по-лесно да го покажем тук, че ще бъде на по-обширен пример, толкова голи за мен. Това е полезно за операции, които винаги ще връщат същата стойност, когато са извикани със същите аргументи, но отнемат повече ресурси по отношение на времето за изпълнение, например

Забележете, че дефинираме променлива cache извън дефиницията на динамичната функция, по същия начин, по който направихме с counter. Ние ще попълваме този обект с ключовете, получени като параметри, когато извикваме динамичната функция и съхраняваме стойността, за да пропуснем изпълнението на, в този опростен случай, Math.pow(subject, power).

Резюме

Сигурен съм, че досега, или поне се надявам да е така, вече сте разбрали по-добре какво представляват затварянията и за какво могат да бъдат полезни. Това е нещо, от което не трябва да се плашим и след като ги разберете и защо работят по начина, по който работят, можете да започнете да се възползвате от пълния потенциал, който идва с тях.