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

Един от често използваните модели за кодиране с функции има изискано име за себе си: Израз на функция с незабавно извикване. Или по-известен като IIFE и се произнася като „iffy“.

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

Определение на естествената функция

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

  1. Редове 1–3 дефинират функция с име sayHi.
  2. На ред 5 го извикваме с обичайния синтаксис „()”, за да извикаме функцията.

Този начин за създаване на функция се нарича „дефиниция на функция“или„декларация на функция“ или „изявление на функция“. Обикновено разработчиците, които са нови в JavaScript, нямат проблеми с използването на този синтаксис, тъй като той много наподобява функциите/методите в други популярни езици за програмиране.

Тези дефиниции на функции винаги започват с ключовата дума function и винаги са последвани от име на функцията. Не можете да пропуснете името, тъй като е невалиден синтаксис.

Функционални изрази

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

Този на пръв поглед прост пример може да ви помогне да издигнете вашите JavaScript умения на следващото ниво.

  1. Ред 1 декларира променлива msg и й присвоява стойност на низ.
  2. Редове 2–4 декларират променлива sayHi и й присвояват стойност от тип функция.
  3. Ред 6 извиква тази функция sayHi.

Ред 1 е тривиален за разбиране. Но когато разработчиците видят редове 2–4 за първи път, това обикновено се противопоставя на очакванията им, ако идват от други езици за програмиране като Java.

По принцип в редове 2–4 присвоихме стойност от тип функция на променлива с име sayHi.

В горния пример функцията от дясната страна на оператора за присвояване често се нарича „функционален израз“. Те са навсякъде в JavaScript. Повечето обратни извиквания, които може да сте написали, често са функционални изрази.

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

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

Анонимни функционални изрази

Е, вече знаете какви са те. Горният пример беше израз на анонимна функция. Те са анонимни, защото нямат име след ключовата дума function.

Наименувани функционални изрази

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

Така че разликата тук е, че функционалният израз има име „фибоначи”, което може да се използва вътре в този функционален израз, за ​​да се самоизвиква рекурсивно. (Има още неща като името на функцията, което се показва в проследяване на стека и т.н., но нека не се тревожим за тях в този урок.)

Достатъчно! Покажете ми IIFE или си тръгвам сега!

Благодарим ви за търпението, а търпението е най-важното умение, необходимо за овладяване на JavaScript!

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

Това е моите приятели, нашият скъп IIFE в действие! Когато копирате този код и опитате в конзолата на браузъра, ще видите предупреждението от кода на ред 2. И това е почти всичко. Никой никога не може да накара този сигнал да се покаже отново.

Това е функция, която умря веднага след като оживя.

Сега нека разберем този не толкова интуитивен синтаксис: знам, че сте забелязали това “!” на ред 1; Ако не го направихте, не се притеснявайте, щяхте да го забележите сега!

  1. Както видяхме преди, изразът за функция винаги започва с ключовата дума function. Всеки път, когато JavaScript вижда ключова дума функция като първа дума във валиден оператор, той очаква, че ще се осъществи дефиниране на функция. Така че, за да предотвратим това да се случи, ние поставяме префикс “!” пред ключовата дума функция на линия 1. Това основно налага JavaScript да третира всичко, което идва след “!” като израз.
  2. Но най-интересните неща се случват на ред 3, където незабавно изпълняваме този функционален израз.

Така че имаме функционален израз, който се извиква веднага след създаването му. И това, приятели мои, се нарича IIFE, независимо от стилистичната вариация, използвана за постигане на този ефект.

Горният стилистичен вариант може да се използва чрез замяна на “!” с “+”, “-”, или дори и „~“. По принцип може да се използва всеки унарен оператор.

Сега опитайте в конзолата! И си поиграйте с IIFE за ваша радост!

Всичко, което първият знак, “!”, прави тук, е да превърне тази функция в израз вместо в оператор/дефиниция на функция. И след това незабавно изпълняваме тази функция.

Друг бърз вариант на това е показан по-долу:

Отново void основно принуждава функцията да се третира като израз.

Всички горепосочени модели са полезни, когато не се интересуваме от върнатата стойност от IIFE.

Но какво ще стане, ако искате върната стойност от IIFE и искате да използвате тази върната стойност другаде? Прочетете, за да научите отговора!

Класически IIFE стил

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

Както видяхме в горните примери за IIFE, ключът към модела IIFE е да вземе функция и да я превърне в израз и да я изпълни незабавно.

Първо, нека видим още един начин за създаване на функционален израз!

В горния код изразът на функция е обвит в скоби в редове 1–3. Това все още не е IIFE, тъй като този израз на функция никога не се изпълнява. Сега, за да преобразуваме този код в IIFE, имаме следните две стилистични вариации:

Сега имаме два IIFE в действие. Може да е наистина трудно да забележите разликата между Вариант 1 и Вариант 2. Нека да обясня това.

  1. Във Вариант 1, на ред 4, скобите () за извикване на израза на функцията се съдържат във външните скоби. Отново са необходими външни скоби, за да се направи израз на функция от тази функция.
  2. Във Вариант 2, на ред 9, скобите () за извикване на функционалния израз са извън опаковъчните скоби за функционалния израз.

И двата варианта се използват широко. Аз лично предпочитам Вариант 1. Ако навлезем в детайлите, и двата варианта леко се различават по начина, по който работят. Но за всички практически цели и запазвайки този вече дълъг урок кратък, ще кажа, че можете да използвате всеки един от тях по ваш вкус. (Ще направя връзка към бъдеща статия, която планирам да напиша за оператора () и оператора запетая, която изяснява нюансите между тези два стила.)

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

Сега знаете защо тези странно изглеждащи заобикалящи скоби около израза на функцията са необходими за формиране на IIFE модел.

Запомни това! Имате нужда от функционален израз, за ​​да формирате IIFE. Функционалните изрази/дефиниции никога не се използват за създаване на IIFE.

IIFE и частни променливи

Едно нещо, в което IIFE са наистина добри, е способността им да създават функционален обхват за IIFE.

Всички променливи, декларирани в IIFE, не са видими за външния свят.

Да видим един пример.

В този пример сме декларирали две променливи вътре в IIFE и те са частни за този IIFE. Никой извън IIFE няма достъп до тях. По подобен начин имаме функция init, до която никой няма достъп извън IIFE. Но функцията init има достъп до тези частни променливи.

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

Когато видим модулен модел, ще обясня как да дадем привилегирован и контролиран достъп до тези частни променливи на света извън IIFE. Така че прочетете, за да знаете, че дори ако вече се чувствате като IIFE Ninja!

IIFE с върната стойност

Ако не се нуждаете от върната стойност от IIFE, тогава винаги можете да използвате първата стилистична IIFE вариация, която видяхме с унарни оператори като !, +, void и др.

Но друга наистина важна и мощна характеристика на IIFE е, че те могат да върнат стойност, която може да бъде присвоена на променлива.

  1. В този вариант имаме IIFE, който има оператор за връщане на ред 2.
  2. Когато изпълним горния код, ред 5 показва предупреждението с върнатата стойност от IIFE.

По принцип IIFE се изпълнява, веднага, разбира се, и след това върнатата стойност от него се присвоява на променливата result.

Това е наистина мощен модел, който ще използваме, докато разглеждаме примера за модел на модул.

IIFE с параметри

Не само IIFE могат да връщат стойности, но IIFE могат също да приемат аргументи, докато се извикват. Нека да видим бърз пример.

  1. В горния пример, на ред 1, IIFE има два формални параметъра, наречени msg, съответно times.
  2. Когато изпълним IIFE на ред 5, вместо празните скоби (), които сме виждали досега, сега предаваме аргументи на IIFE.
  3. Редове 2 и 3 използват тези параметри вътре в IIFE.

Това е наистина мощен модел и го виждаме често в кода на jQuery и в други библиотеки.

В горния пример предаваме jQuery, прозорец,идокументкато аргументи към IIFE на ред 3. Кодът вътре в IIFE може да ги обозначава като $, глобален, документсъответно.

Ето няколко предимства от предаването им на IIFE.

  1. JavaScript винаги търси обхват от обхвата на текущата функция и продължава да търси в по-високи обхвати, докато намери идентификатор. Когато предаваме документ на ред 3, това е единственият път, когато правим търсене на обхват извън локалния обхват за документа. Всички препратки в IIFE към документ никога няма да трябва да се търсят извън локалния обхват на IIFE. Същото важи и за jQuery. Увеличаването на производителността от това може да не е огромно въз основа на това колко тривиален или сложен е кодът на IIFE, но все пак това е полезен трик, който трябва да знаете.
  2. Освен това минификаторите на JavaScript могат безопасно да минимизират имената на параметрите, декларирани във функция. Ако не сме ги предали като параметри, минификаторите не намаляват директните препратки към документ или jQuery, тъй като те са извън обхвата на тази функция.

Класически модел на JavaScript модул

Сега, след като сте усвоили IIFE, нека видим пример за модел на модул, който поставя IIFE и затваряния на стероиди.

Ще внедрим класически единичен обект Sequence, който работи безпроблемно, без някой да може случайно да повреди текущата стойност на последователността.

Ще напишем този код в две стъпки, за да разберем какво се случва постепенно.

  1. В горния пример имаме IIFE, който връща обект. Вижте ред 7 и 8.
  2. Имаме и локална променлива в IIFE, наречена current.
  3. Върнатата стойност на IIFE, която е обект в този пример, е присвоена на променливата Sequence. Ред 12 правилно предупреждава „обект“, тъй като връщаме обект от IIFE.

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

  1. В този пример добавяме две функции към обекта, който връщаме от IIFE.
  2. Редове 8–10 добавят функция getCurrentValue, която връща стойността в променлива current
  3. Редове 12–15 добавят функция getNextValue, която увеличава стойността в current с 1 и след това връща стойността в ток.

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

(Ако искате да овладеете затварянията, моля, прочетете моя невероятен и вирусен урок за затваряния: Изучаване на затваряния на JavaScript чрез законите на кармата.)

Това е наистина мощен JavaScript модел, който сте научили. Той съчетава силата както на IIFE, така и на затваряния.

Това е много основен вариант на модела на модула. Има повече модели, но почти всички от тях използват IIFE за създаване на частен обхват на затваряне.

Когато можете да пропуснете скобите

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

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

В горния пример ключовата дума функция не е първата дума в израза. Така че JavaScript не третира това като оператор/дефиниция на функция. По подобен начин има други места, където можете да пропуснете скоби, когато знаете, че това е израз.

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

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

Обичам да пиша тези уроци по JavaScript. Толкова е забавно да ги пишеш. Но те наистина отнемат много време и усилия, за да се полират и публикуват. Ако сте намерили този урок за полезен, можете да „ръкопляскате“, за да покажете своята благодарност и да помогнете да препоръчате този урок на други. Моля, следвайте ме тук в Medium, а също и в Twitter, за да получавате актуализации при всяко публикуване на нова статия.

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

Сега, това беше много JavaScript, поемете дълбоко дъх и си направете почивка от JavaScript, като прочетете последната ми публикация.



Другите ми уроци по JavaScript тук: