Funkcja to nazwany blok kroków
Za każdym razem, gdy chcesz nadać kawałkowi logiki nazwę i użyć go ponownie, piszesz funkcję. Najstarszy i najprostszy sposób w JavaScript to deklaracja funkcji: słowo kluczowe function, a po nim nazwa.
Czytając to po kolei:
functionto słowo kluczowe, które rozpoczyna deklarację.greetto nazwa funkcji.(name)to lista parametrów, czyli danych wejściowych funkcji.- Blok w nawiasach klamrowych to ciało funkcji.
greet("Ada")to wywołanie. JavaScript uruchamia ciało funkcji znameustawionym na"Ada".
Zdefiniowanie funkcji jej nie uruchamia. Uruchamia ją dopiero wywołanie.
Parametry i argumenty
Parametr to nazwa w definicji funkcji. Argument to wartość przekazywana przy wywołaniu. Na co dzień używa się tych słów zamiennie, ale różnica ma znaczenie przy czytaniu komunikatów o błędach.
Tutaj base i exponent to parametry. 2 i 10 to argumenty. JavaScript wiąże je po kolei: pierwszy argument z pierwszym parametrem i tak dalej.
W przeciwieństwie do niektórych języków JavaScript nie narzeka, gdy przekażesz złą liczbę argumentów. Brakujące stają się undefined, nadmiarowe są po cichu ignorowane. To elastyczne, ale czasem bywa pułapką. Wartości domyślne i parametry rest omawiamy w kolejnych artykułach.
return oddaje wartość
console.log wypisuje coś na wyjście. return oddaje wartość temu, kto wywołał funkcję, żeby mógł jej użyć:
Bez return funkcja zwraca undefined:
return natychmiast kończy też funkcję. Wczesne zwracanie to standardowy sposób na obsłużenie przypadków brzegowych przed główną logiką:
Dzięki wczesnym returnom główne ciało funkcji nie zamienia się w piramidę if/else.
Hoisting: możesz wywołać funkcję przed jej definicją
To naprawdę zaskakuje osoby przychodzące z innych języków. Deklaracje funkcji podlegają hoistingowi: JavaScript przenosi je na początek ich zakresu, zanim uruchomi jakikolwiek kod. Oznacza to, że możesz wywołać funkcję w linii powyżej jej deklaracji:
Ten kod działa bez problemu. Przed wykonaniem silnik przegląda zakres, rejestruje square jako funkcję i dopiero potem wykonuje instrukcje od góry do dołu.
To realna różnica w zachowaniu między deklaracjami funkcji a innymi sposobami tworzenia funkcji (wyrażeniami funkcyjnymi, funkcjami strzałkowymi). Te drugie są hoistowane jak zmienne: nazwa jest znana, ale wartość zostaje przypisana dopiero wtedy, gdy wykona się dana linia. Więcej o tej różnicy za chwilę.
Większość przewodników stylu i tak zaleca definiowanie funkcji przed ich wywołaniem. Hoisting to siatka bezpieczeństwa, a nie styl, na którym warto polegać.
Deklaracje kontra wyrażenia
Deklaracja funkcji stoi samodzielnie jako instrukcja. Wyrażenie funkcyjne pojawia się tam, gdzie oczekiwana jest wartość, najczęściej po prawej stronie przypisania:
Oba sposoby dają funkcje, które da się wywołać. Różnice:
- Deklaracje są hoistowane w całości. Wyrażenia podlegają zasadom hoistingu zmiennej, do której są przypisane (
constiletsą w temporal dead zone, dopóki nie wykona się ich linia). - Deklaracje muszą mieć nazwę. Wyrażenia mogą być anonimowe, choć nazwanie ich pomaga w czytaniu stack trace.
- Deklaracje nie mogą stać byle gdzie. W trybie ścisłym
function foo() {}wewnątrz blokuifzachowuje się różnie w różnych silnikach, więc tam lepiej użyć wyrażenia.
Dla większości funkcji pomocniczych na najwyższym poziomie pliku deklaracja czyta się dobrze. Dla funkcji przekazywanych jako argumenty lub przypisywanych do właściwości zwykle wybiera się wyrażenie (albo funkcję strzałkową).
Nazewnictwo i styl
Nazwa funkcji to obietnica tego, co funkcja robi. Kilka dodatkowych znaków na opisową nazwę zwraca się już przy pierwszym czytaniu kodu przez kogoś innego.
Kilka konwencji, które warto przyjąć:
- Nazwy funkcji powinny być czasownikami:
fetchProfile,computeTotal,sendEmail. - Używaj
camelCase, to norma w JavaScript. - Funkcje zwracające wartość logiczną często zaczynają się od
is,haslubcan:isValid,hasAccess,canEdit.
Chodzi o to, żeby miejsce wywołania czytało się jak zdanie.
Mały działający przykład
Wszystko razem: parametry, wczesny return, opisowa nazwa:
Jedna deklaracja, klauzula ochronna, czytelny return. Taki kształt ma większość funkcji, które napiszesz.
Dalej: funkcje strzałkowe
Deklaracje to koń pociągowy, ale nowoczesny JavaScript mocno opiera się na krótszej składni, czyli funkcjach strzałkowych, zwłaszcza w callbackach i jednolinijkowcach. Wyglądają inaczej, inaczej zachowują się wobec this i właśnie o nich jest następna strona.
Najczęściej zadawane pytania
Jak zadeklarować funkcję w JavaScript?
Użyj słowa kluczowego function, potem nazwy, nawiasów z parametrami i bloku. Przykład: function greet(name) { return 'Hi, ' + name; }. Wywołujesz ją, pisząc nazwę z nawiasami: greet('Ada').
Czym jest hoisting funkcji w JavaScript?
Deklaracje funkcji są przenoszone na początek otaczającego zakresu, zanim kod się uruchomi, więc możesz je wywołać w linii powyżej miejsca, w którym są zapisane. Dotyczy to tylko deklaracji function. Wyrażenia funkcyjne i funkcje strzałkowe przypisane do let lub const nie są hoistowane w ten sam sposób.
Czym różni się deklaracja funkcji od wyrażenia funkcyjnego?
Deklaracja jest samodzielną instrukcją (function greet() {}) i podlega hoistingowi. Wyrażenie przypisuje funkcję do zmiennej (const greet = function() {}) i podlega zwykłym zasadom hoistingu zmiennych. Deklaracje z definicji mają nazwę, wyrażenia często są anonimowe.