Funkcja strzałkowa to krótszy zapis funkcji w JavaScripcie (od ES6), w którym zamiast słowafunctionużywasz=>, np.const dodaj = (a, b) => a + b. Różni się od zwykłej funkcji tym, że nie ma własnegothisaniargumentsi nie można jej wywołać znew. Dlatego świetnie działa w callbackach (map,filter,setTimeout), ale nie nadaje się na metody obiektu ani konstruktory.
Funkcje strzałkowe widać w prawie każdym nowoczesnym kodzie JavaScript, w React, w metodach tablicowych i w obsłudze zdarzeń. Na początku wyglądają obco, bo => zastępuje całe słowo function. W tym artykule pokażę, jak je zapisywać, jak zamienić na nie zwykłą funkcję krok po kroku, czym się różnią od funkcji deklarowanej przez function i kiedy lepiej ich nie używać.
Czym jest funkcja strzałkowa w JavaScript?
Funkcja strzałkowa (ang. arrow function) to skrócony zapis funkcji wprowadzony w standardzie ES6 (2015). Zamiast słowa function piszesz listę parametrów, strzałkę => i ciało funkcji. Poniższe dwie funkcje robią to samo:
// zwykła funkcja
const dodaj = function (a, b) {
return a + b;
};
// funkcja strzałkowa
const dodajStrzalka = (a, b) => {
return a + b;
};
console.log(dodaj(2, 3)); // 5
console.log(dodajStrzalka(2, 3)); // 5
Funkcja strzałkowa jest zawsze wyrażeniem funkcyjnym, więc zwykle przypisujesz ją do zmiennej (const) albo przekazujesz od razu jako argument. Nie ma odpowiednika „deklaracji” w stylu function dodaj() {}. Jeśli dopiero poznajesz funkcje, zacznij od deklaracji i wywołania funkcji w JavaScript, a potem wróć tutaj.
Jak zapisać funkcję strzałkową? Składnia krok po kroku
Składnia ma kilka wariantów, zależnie od liczby parametrów i tego, co funkcja robi:
| Sytuacja | Zapis | Uwaga |
|---|---|---|
| Brak parametrów | () => 42 | nawiasy są obowiązkowe |
| Jeden parametr | x => x * 2 | nawiasy można pominąć |
| Wiele parametrów | (a, b) => a + b | nawiasy są obowiązkowe |
| Wartość domyślna lub destrukturyzacja | (a, b = 2) => a + b | nawiasy są obowiązkowe |
| Kilka instrukcji | x => { const y = x * 2; return y; } | klamry wymagają return |
| Jedno wyrażenie | x => x * 2 | return dzieje się „po cichu” |
Najważniejsza zasada: bez klamer funkcja zwraca wynik wyrażenia po strzałce (to tzw. niejawny return), a z klamrami to zwykły blok, w którym musisz sam napisać return.
const a = x => x * 2; // bez klamer: zwraca wynik
const b = x => { x * 2 }; // z klamrami, bez return: zwraca undefined
console.log(a(4)); // 8
console.log(b(4)); // undefined
Drugi zapis to jeden z najczęstszych błędów początkujących. Funkcja się wykona, ale wyniku nie zwróci.
Jak zamienić zwykłą funkcję na funkcję strzałkową w najprostszy sposób?
Przejdźmy to w czterech krokach, na jednym przykładzie. Zaczynamy od zwykłej funkcji:
function podwoj(liczba) {
return liczba * 2;
}
Krok 1. Zamień deklarację na zmienną. Usuń słowo function, a nazwę przenieś do const:
const podwoj = (liczba) => {
return liczba * 2;
};
Po nawiasie z parametrami dopisałeś =>. To jest właściwa zamiana, reszta to już skracanie.
Krok 2. Jeśli ciało to samo return, usuń klamry i słowo return:
const podwoj = (liczba) => liczba * 2;
Krok 3. Jeśli jest dokładnie jeden parametr, usuń nawiasy:
const podwoj = liczba => liczba * 2;
Krok 4. Jeśli funkcja zwraca obiekt, owiń go w nawiasy okrągłe. Bez nich JavaScript uzna klamry za blok kodu (więcej w następnej sekcji):
const stworzUzytkownika = imie => ({ imie, aktywny: true });
Tak samo zamieniasz funkcję anonimową w callbacku. Zapis tablica.map(function (x) { return x * 2; }) zmienia się w tablica.map(x => x * 2).
Zanim zamienisz, sprawdź cztery rzeczy. Jeśli któraś z nich dotyczy Twojej funkcji, zostaw ją zwykłą:
- używa
this(np. jest metodą obiektu albo handlerem, który ma widzieć element, na którym nasłuchujesz), - używa
arguments, - jest konstruktorem wywoływanym z
new, - jest wywoływana przed miejscem, w którym ją zdefiniowałeś (deklaracja
functiondziała wcześniej, strzałka przypisana doconstnie).
Jak zwrócić obiekt z funkcji strzałkowej?
Tu jest pułapka, na którą wpada prawie każdy. Klamry po strzałce JavaScript traktuje jako blok kodu, a nie jako obiekt:
const zle = id => { id }; // blok z instrukcją "id", brak return
const dobrze = id => ({ id }); // nawiasy okrągłe: to obiekt
console.log(zle(1)); // undefined
console.log(dobrze(1)); // { id: 1 }
const lista = [1, 2].map(id => ({ id }));
console.log(lista); // [ { id: 1 }, { id: 2 } ]
Wystarczy owinąć obiekt w nawiasy okrągłe, a silnik zrozumie, że to wyrażenie. Bez nawiasów map zwróciłby tablicę undefinedów.
Czym funkcja strzałkowa różni się od zwykłej funkcji?
Obie służą do tego samego, ale zachowują się inaczej w kilku miejscach. Poniżej zebrane różnice, które mają znaczenie w praktyce:
| Cecha | Zwykła funkcja (function) | Funkcja strzałkowa (=>) |
|---|---|---|
this | własny, zależy od tego, jak funkcję wywołano | brak własnego, bierze this z miejsca, w którym ją zapisano |
arguments | jest | brak (użyj parametru ...args) |
Wywołanie z new | działa (konstruktor) | TypeError: ... is not a constructor |
prototype | jest | undefined |
| Użycie przed definicją | deklaracja działa (hoisting) | ReferenceError, bo to wartość w const |
| Zapis | dłuższy | krótszy, z niejawnym return |
Dwie z tych różnic zobaczysz w praktyce najczęściej: this i brak konstruktora.
const A = () => {};
try {
new A();
} catch (e) {
console.log(e.message); // A is not a constructor
}
function zwykla() {
console.log(arguments.length);
}
zwykla(1, 2, 3); // 3
const strzalka = (...args) => console.log(args.length);
strzalka(1, 2, 3); // 3
Czy funkcja strzałkowa ma własne this?
Nie. To najważniejsza różnica. Zwykła funkcja ustala this w momencie wywołania („to, co jest po lewej stronie kropki”), a funkcja strzałkowa bierze this z otoczenia, w którym ją zapisałeś.
Dlatego strzałka jest wygodna w callbackach wewnątrz klasy:
class Licznik {
wartosc = 0;
start() {
setTimeout(() => {
this.wartosc++; // this to nadal obiekt Licznik
console.log(this.wartosc); // 1
}, 10);
}
}
new Licznik().start();
Zwykła funkcja w setTimeout dostałaby własne this i this.wartosc przestałoby działać. Pełne wyjaśnienie z przykładami znajdziesz w artykule dlaczego this nie działa w JavaScript.
Ta sama cecha, która pomaga w callbackach, szkodzi w metodach obiektu:
const osoba = {
imie: "Ala",
powitanie: () => this?.imie, // strzałka: this nie wskazuje na obiekt "osoba"
powitanieZwykla() { return this.imie; }
};
console.log(osoba.powitanie()); // undefined
console.log(osoba.powitanieZwykla()); // "Ala"
W metodzie obiektu piszesz więc zwykłą funkcję albo skrócony zapis metody (powitanieZwykla() { ... }), a nie strzałkę.
Jak użyć funkcji strzałkowej w callbacku?
Najczęstsze zastosowanie to krótkie callbacki w metodach tablicowych i zdarzeniach. Strzałka sprawia, że kod mieści się w jednej linii:
const liczby = [1, 2, 3, 4];
const sumaKwadratowParzystych = liczby
.filter(n => n % 2 === 0)
.map(n => n * n)
.reduce((suma, n) => suma + n, 0);
console.log(sumaKwadratowParzystych); // 20
Jeśli nie wiesz jeszcze, czym jest callback, przeczytaj najpierw callback functions w JavaScript. Więcej o map, filter i reduce znajdziesz w metodach tablicowych w JavaScript.
Jak zapisać asynchroniczną funkcję strzałkową (async)?
Słowo async piszesz przed parametrami:
const czekaj = ms => new Promise(resolve => setTimeout(resolve, ms));
const podwojPoChwili = async x => {
await czekaj(5);
return x * 2;
};
console.log(await podwojPoChwili(3)); // 6
Przy jednym parametrze nawiasy nadal można pominąć (async x => ...), a bez parametrów piszesz async () => .... Uważaj na map z funkcją async. Zwraca ona tablicę obietnic, a nie wyniki:
const obietnice = [1, 2].map(async x => x * 2);
console.log(obietnice); // [ Promise { 2 }, Promise { 4 } ]
console.log(await Promise.all(obietnice)); // [ 2, 4 ]
Żeby dostać wartości, opakuj wynik w Promise.all. Dalsze kroki z kodem asynchronicznym opisujemy w artykule o testowaniu kodu asynchronicznego w JavaScript.
Co oznaczają dwie strzałki pod rząd (a => b => ...)?
To funkcja, która zwraca inną funkcję. Taki zapis spotkasz w React i w bibliotekach funkcyjnych. Czytaj go od lewej: pierwsza strzałka przyjmuje a i zwraca drugą funkcję, która przyjmuje b.
const dodaj = a => b => a + b;
const dodajDwa = dodaj(2);
console.log(dodajDwa(3)); // 5
console.log(dodaj(2)(3)); // 5
Na początku nie musisz tego pisać samodzielnie. Wystarczy, że rozpoznasz taki wzorzec w cudzym kodzie.
Kiedy nie używać funkcji strzałkowej?
Zostaw zwykłą funkcję (albo metodę klasy), gdy:
- piszesz metodę obiektu, która korzysta z
this, - tworzysz konstruktor wywoływany z
newalbo dopisujesz metodę doprototype, - potrzebujesz własnego
arguments, - chcesz, żeby
thiswskazywało na element w handlerze zdarzenia (strzałka go nie przejmie), - funkcja musi być dostępna przed miejscem, w którym ją zapisałeś (hoisting deklaracji).
W pozostałych przypadkach, czyli w krótkich callbackach i funkcjach pomocniczych, strzałka jest dobrym wyborem.
Jakie błędy z funkcjami strzałkowymi zdarzają się najczęściej?
| Błąd | Skutek | Jak naprawić |
|---|---|---|
x => { x * 2 } | zwraca undefined | usuń klamry albo dodaj return |
id => { id } zamiast obiektu | undefined | id => ({ id }) |
| strzałka jako metoda obiektu | this nie wskazuje na obiekt | zwykła funkcja lub skrócony zapis metody |
new na funkcji strzałkowej | TypeError: ... is not a constructor | zwykła funkcja lub class |
użycie arguments | ReferenceError lub argumenty z zewnętrznej funkcji | parametr ...args |
nowa linia przed => | SyntaxError: Unexpected token '=>' | strzałka musi być w tej samej linii co ), nową linię można dać dopiero po niej |
| wywołanie przed definicją | ReferenceError: Cannot access ... before initialization | przenieś definicję wyżej |
Po błędach najlepiej uczyć się, pisząc własny kod. Jeśli chcesz przejść ścieżkę od podstaw JavaScriptu do projektów z mentorem, zobacz nasz kurs JavaScript.
Podsumowanie
Funkcja strzałkowa to krótszy zapis funkcji, z niejawnym return przy jednym wyrażeniu i bez własnego this. Zamiana zwykłej funkcji na strzałkową sprowadza się do usunięcia słowa function i dopisania =>, a skracanie jest już opcjonalne. Używaj jej w callbackach, a zwykłej funkcji w metodach obiektu i konstruktorach.


