Jak definiować funkcje w JavaScript?

Jeśli dopiero zaczynasz swoją przygodę z JavaScriptem, pewnie szybko natknąłeś się na pojęcie funkcji. I bardzo dobrze! Bo funkcje to absolutny fundament każdego języka programowania. Bez nich Twój kod byłby jednym wielkim chaosem — powtarzającym te same linijki raz za razem. Dzięki funkcjom możesz zorganizować kod, uniknąć powtórek i pisać bardziej czytelne oraz wydajne programy.

W tym artykule pokażę Ci jak definiować funkcje w JavaScript na różne sposoby, czym się one różnią, oraz jak poprawnie z nich korzystać. Zrobimy to krok po kroku, na konkretnych przykładach. Gotowy? No to zaczynajmy!

Czym w ogóle jest funkcja?

Zanim przejdziemy do definicji, warto wiedzieć, czym funkcja w ogóle jest.

Funkcja w JavaScript to fragment kodu, który wykonuje określone zadanie. Można ją wywołać (czyli uruchomić) w dowolnym momencie programu. Często funkcja przyjmuje dane wejściowe (tzw. argumenty) i zwraca jakiś wynik (wartość zwracaną).

Brzmi technicznie? Okej, zobaczmy prosty przykład:

function powitaj() {
  console.log("Cześć! Miło Cię widzieć!");
}

powitaj();

Po uruchomieniu tego kodu w konsoli zobaczysz komunikat:

Cześć! Miło Cię widzieć!

To jest właśnie funkcja — niewielki, samodzielny fragment kodu, który możesz uruchamiać kiedy chcesz.

Klasyczny sposób: function declaration

Najbardziej tradycyjny (i wciąż bardzo popularny) sposób definiowania funkcji to tzw. deklaracja funkcji.

Składnia:

function nazwaFunkcji(parametr1, parametr2, ...) {
  // ciało funkcji
  return wynik;
}

Przykład:

function dodaj(a, b) {
  return a + b;
}

console.log(dodaj(3, 5)); // 8

Proste, prawda?
Ta forma ma jedną ciekawą właściwość: hoisting.

Co to jest hoisting? (nie mylić z hostingiem)

W JavaScript wszystkie deklaracje funkcji są „podnoszone” na początek zakresu (czyli są dostępne w kodzie, nawet jeśli je wywołasz przed faktyczną deklaracją).

powiedzCzesc();

function powiedzCzesc() {
  console.log("Hej!");
}

Ten kod zadziała, mimo że wywołanie funkcji jest przed jej definicją.
Dla początkujących to czasem zaskoczenie, ale to bardzo przydatna cecha!

Alternatywa: function expression

Drugim sposobem jest przypisanie funkcji do zmiennej. To tzw. wyrażenie funkcyjne.

Składnia:

const nazwa = function(parametr1, parametr2) {
  return wynik;
};

Przykład:

const pomnoz = function(a, b) {
  return a * b;
};

console.log(pomnoz(4, 6)); // 24

Zwróć uwagę, że tu funkcja nie ma nazwy (to tzw. funkcja anonimowa) i jest przypisana do zmiennej pomnoz.

W odróżnieniu od deklaracji funkcji — tutaj nie działa hoisting.
Jeśli spróbujesz wywołać pomnoz() przed jej zdefiniowaniem, dostaniesz błąd.

Funkcje strzałkowe (arrow functions)

Od momentu wprowadzenia ES6 (czyli nowoczesnego JavaScriptu), pojawiła się nowa, krótsza składnia: funkcje strzałkowe.
To właśnie one stały się hitem wśród programistów.

Składnia:

const nazwa = (parametr1, parametr2) => {
  // ciało funkcji
  return wynik;
};

A jeśli funkcja ma tylko jeden parametr i zwraca jedną wartość, można skrócić to jeszcze bardziej:

const podwoj = x => x * 2;

Tak! To cały kod.

Przykład:

const powitaj = (imie) => {
  console.log(`Cześć, ${imie}!`);
};

powitaj("Kasia");

lub w wersji skróconej:

const powitaj = imie => console.log(`Cześć, ${imie}!`);

Prosto, prawda?

Różnice między function a =>

No dobra, skoro można pisać krócej, to po co używać tej starszej składni?
Otóż różnice między tymi dwoma sposobami są bardzo istotne — szczególnie w kontekście słowa kluczowego this.

W klasycznej funkcji function, słowo this wskazuje na obiekt, który wywołał funkcję.

W funkcji strzałkowej this nie tworzy się na nowo, tylko dziedziczy kontekst z miejsca, w którym funkcja została napisana.

Przykład:

const obiekt = {
  imie: "Ania",
  przywitaj: function() {
    console.log(`Cześć, jestem ${this.imie}`);
  }
};

obiekt.przywitaj(); // Cześć, jestem Ania

Ale jeśli zmienimy function na strzałkę:

const obiekt = {
  imie: "Ania",
  przywitaj: () => {
    console.log(`Cześć, jestem ${this.imie}`);
  }
};

obiekt.przywitaj(); // Cześć, jestem undefined

Dlaczego?
Bo w funkcjach strzałkowych this nie odnosi się do obiektu, tylko do kontekstu, w którym funkcja została utworzona — czyli w tym przypadku do window (w przeglądarce).

Dlatego funkcji strzałkowych nie powinno się używać jako metod obiektu.

Funkcje anonimowe i natychmiastowo wywoływane (IIFE)

Czasem chcemy stworzyć funkcję, która wykona się natychmiast po zdefiniowaniu.
Takie konstrukcje nazywamy IIFE (Immediately Invoked Function Expression).

Przykład:

(function() {
  console.log("To jest IIFE — wykonało się samo!");
})();

Tak, ta funkcja wywoła się automatycznie.
To stary, ale skuteczny sposób na tworzenie „zamkniętego” kodu, który nie zaśmieca globalnego zakresu zmiennych.

Parametry domyślne w funkcjach

JavaScript pozwala nadawać wartości domyślne parametrom.
To oznacza, że jeśli nie podasz argumentu, funkcja użyje wartości zapasowej.

Przykład:

function powitaj(imie = "Nieznajomy") {
  console.log(`Cześć, ${imie}!`);
}

powitaj(); // Cześć, Nieznajomy!
powitaj("Ola"); // Cześć, Ola!

Świetne, prawda? Dzięki temu kod jest bardziej odporny na błędy.

Funkcje jako argumenty (callbacki)

Jedną z najpotężniejszych cech JavaScriptu jest możliwość przekazywania funkcji jako argumentów do innych funkcji.

Przykład:

function wykonajOperacje(a, b, callback) {
  return callback(a, b);
}

const dodaj = (x, y) => x + y;
const pomnoz = (x, y) => x * y;

console.log(wykonajOperacje(3, 4, dodaj)); // 7
console.log(wykonajOperacje(3, 4, pomnoz)); // 12

Tutaj callback to funkcja przekazywana jako argument.
To właśnie na tej zasadzie działa np. setTimeout czy Array.map().

Funkcje strzałkowe w praktyce — przykład z kodem

Zróbmy coś bardziej praktycznego. Załóżmy, że mamy tablicę imion i chcemy wypisać każde z nich wielkimi literami.

Kod:

const imiona = ["Ola", "Ania", "Tomek", "Marek"];

const wielkieLitery = imiona.map(imie => imie.toUpperCase());

console.log(wielkieLitery);
// ["OLA", "ANIA", "TOMEK", "MAREK"]

Tutaj użyliśmy funkcji strzałkowej jako callbacka w metodzie .map() — to idealny przykład, kiedy taka funkcja ma sens.

Funkcje zagnieżdżone

Funkcje mogą być też zagnieżdżane, czyli definiowane wewnątrz innych funkcji.

Przykład:

function zewnetrzna() {
  console.log("To funkcja zewnętrzna.");

  function wewnetrzna() {
    console.log("To funkcja wewnętrzna.");
  }

  wewnetrzna();
}

zewnetrzna();

Taki zabieg jest przydatny, gdy chcesz ukryć jakąś część logiki i nie udostępniać jej poza daną funkcją.

Funkcje jako wartości zwracane

Tak, w JavaScript funkcje mogą zwracać inne funkcje.
To potężna koncepcja znana z tzw. funkcji wyższego rzędu.

Przykład:

function stworzPowitanie(imie) {
  return function() {
    console.log(`Cześć, ${imie}!`);
  };
}

const powitajAnie = stworzPowitanie("Ania");
powitajAnie(); // Cześć, Ania!

Brzmi magicznie? W rzeczywistości to bardzo praktyczny mechanizm — często używany np. w React czy Node.js.

Funkcje asynchroniczne (async / await)

Na koniec nie sposób nie wspomnieć o funkcjach asynchronicznych.
JavaScript często działa z operacjami, które trwają (np. pobieranie danych z serwera).
Zamiast blokować cały program, można użyć funkcji asynchronicznych.

Przykład:

async function pobierzDane() {
  const odpowiedz = await fetch("https://jsonplaceholder.typicode.com/posts/1");
  const dane = await odpowiedz.json();
  console.log(dane);
}

pobierzDane();

Tutaj async oznacza, że funkcja zwraca Promise, a await pozwala nam „poczekać” na wynik operacji.
Dzięki temu kod wygląda jak synchroniczny, ale działa asynchronicznie — piękne połączenie prostoty i mocy!

Jak widzisz, definiowanie funkcji w JavaScript to temat, który ma wiele twarzy.
Możesz użyć klasycznej składni, nowoczesnych funkcji strzałkowych, a nawet tworzyć funkcje, które zwracają inne funkcje. Wszystko zależy od tego, co chcesz osiągnąć.

Oto szybkie podsumowanie:

Typ funkcjiSkładniaCechy
Deklaracjafunction nazwa() {}Wspiera hoisting, klasyczna forma
Wyrażenie funkcyjneconst nazwa = function() {}Brak hoistingu, funkcja anonimowa
Funkcja strzałkowaconst nazwa = () => {}Krótsza składnia, brak własnego this
IIFE(function() {})()Wykonuje się natychmiast
Asynchronicznaasync function nazwa() {}Używana do pracy z Promise i await

Szukasz taniego i dobrego hostingu dla swojej strony www? - Sprawdź Seohost.pl