Menu

Parametry domyślne w JavaScript: praktyczny przewodnik

Jak działają parametry w JavaScript: wartości domyślne, kiedy uruchamia je undefined, kolejność obliczania i różnica między parametrami a argumentami.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Parametry vs argumenty

Dwa słowa, które ciągle się mylą. Parametr to nazwa w definicji funkcji. Argument to wartość, którą przekazujesz przy wywołaniu. Ta sama idea co w Pythonie i większości innych języków:

a i b to parametry. 2 i 3 to argumenty. JavaScript wiąże je według pozycji: pierwszy argument z pierwszym parametrem i tak dalej. Różnica jest niewielka, ale tego słownictwa używają komunikaty o błędach i MDN.

JavaScript luźno podchodzi do liczby argumentów

W przeciwieństwie do wielu języków JavaScript nie przejmuje się, gdy przekażesz za mało albo za dużo argumentów. Brakujące parametry stają się undefined. Nadmiarowe są po cichu ignorowane:

Pierwsze wywołanie wypisuje Hello, Ada undefined: last nie dostał wartości, więc jest undefined, a template literals chętnie to wstawiają. Bez błędu, bez ostrzeżenia. Ta pobłażliwość czasem się przydaje, a czasem jest źródłem błędów, i właśnie dlatego istnieją parametry domyślne.

Ustawianie wartości domyślnej

Po nazwie parametru wstaw = i wartość. Jeśli wywołujący nie przekaże tego argumentu (albo przekaże undefined), wkracza wartość domyślna:

Wszystkie trzy wywołania działają. Pierwsze i trzecie uruchamiają wartość domyślną, drugie używa przekazanej wartości. To składnia ES6: przed 2015 rokiem trzeba było pisać w ciele funkcji name = name || "friend", co miało własne błędy przy wartościach falsy, takich jak 0 i "".

Wartości domyślne mogą być dowolnym wyrażeniem, nie tylko literałem:

Wyrażenie jest obliczane przy każdym wywołaniu, a nie raz przy definiowaniu funkcji. Nie ma więc pułapki mutowalnych wartości domyślnych, jaką ma Python: każde wywołanie dostaje świeże new Date().

Wartość domyślną uruchamia tylko undefined

To zasada, która zaskakuje. Wartości domyślne działają, gdy argument to undefined, a nie gdy jest falsy, i nie wtedy, gdy to null:

Tylko ostatnie wywołanie używa "friend". Jawne przekazanie null znaczy "wartość to null" i JavaScript bierze cię za słowo. To samo dotyczy pustych stringów i zer: to wartości, a nie brakujące argumenty.

Jeśli chcesz traktować null tak samo jak brak argumentu, musisz to obsłużyć samodzielnie:

Operator ?? (nullish coalescing) traktuje i null, i undefined jako "brak". Więcej o nim w jednym z kolejnych rozdziałów.

Wartości domyślne mogą korzystać z wcześniejszych parametrów

Parametry są obliczane od lewej do prawej, więc późniejsza wartość domyślna może używać każdego parametru, który był przed nią:

Wywołanie z jednym argumentem daje sześcian. Dwa argumenty dają graniastosłup o kwadratowej podstawie. Kierunek ma znaczenie: nie możesz odwołać się do parametru, który nie został jeszcze zadeklarowany:

function bad(a = b, b = 1) {
  return a + b;
}

bad();   // ReferenceError: Cannot access 'b' before initialization

Te same zasady co przy zmiennych zadeklarowanych przez let: użycie przed deklaracją to błąd.

Wartości domyślne a destrukturyzacja

Możesz jednocześnie destrukturyzować parametry i nadawać im wartości domyślne. To popularny wzorzec dla argumentów w postaci "obiektu opcji":

Działają tu dwie warstwy wartości domyślnych. Wewnętrzne (role = "member", active = true) uzupełniają brakujące właściwości. Zewnętrzne = {} obsługuje przypadek, w którym wywołujący w ogóle nie przekaże argumentu: bez niego createUser() próbowałoby destrukturyzować undefined i rzuciłoby błąd.

Na początku ten wzorzec wygląda gęsto, ale jest wszędzie we współczesnym kodzie JavaScript. Gdy oko zacznie rozpoznawać { ... } = {} jako "opcje z wartościami domyślnymi", czyta się go szybko.

Pomijanie środkowego argumentu

JavaScript nie ma argumentów nazwanych jak w Pythonie. Żeby pominąć środkowy parametr i użyć jego wartości domyślnej, przekazujesz jawnie undefined:

Przekazanie undefined jako prefix zachowuje wartość domyślną. To brzydkie. Jeśli często piszesz undefined w wywołaniach, to sygnał, żeby przejść na obiekt opcji:

Teraz wywołujący nazywa to, co chce nadpisać, a kolejność nie ma znaczenia.

Wartości domyślne nie wliczają się do length

Drobny szczegół, który rzadko ma znaczenie, ale czasem wprowadza w błąd. Właściwość length funkcji podaje liczbę parametrów przed pierwszym parametrem z wartością domyślną:

Biblioteki, które analizują funkcje (na przykład niektóre narzędzia do testów i wstrzykiwania zależności), używają length do liczenia "wymaganych" parametrów. Dobrze wiedzieć, że taka zasada istnieje, ale nie warto jej zapamiętywać, chyba że piszesz tego typu narzędzie.

Dalej: rest i spread

Wartości domyślne obsługują przypadek, gdy znasz parametry z góry. Czasem ich nie znasz: chcesz, żeby funkcja przyjmowała dowolną liczbę argumentów, albo przekazać zestaw argumentów do innej funkcji. Do tego służą ...rest i operator spread, o których w następnej części.

Najczęściej zadawane pytania

Jak ustawić domyślną wartość parametru w JavaScript?

W sygnaturze funkcji po nazwie parametru wstaw = i wartość domyślną: function greet(name = 'friend') { ... }. Jeśli wywołujący nie przekaże wartości (albo przekaże undefined), zostanie użyta wartość domyślna. To składnia ES6 i działa we wszystkich współczesnych środowiskach JavaScript.

Jaka jest różnica między parametrami a argumentami?

Parametry to nazwy w definicji funkcji: function add(a, b) ma parametry a i b. Argumenty to rzeczywiste wartości przekazywane przy wywołaniu: add(2, 3) przekazuje argumenty 2 i 3. To rozróżnienie przydaje się przy czytaniu komunikatów o błędach i dokumentacji.

Czy parametr domyślny działa, gdy przekażę null?

Nie. Wartości domyślne działają tylko wtedy, gdy argument to undefined (albo w ogóle go nie ma). Jawne przekazanie null oznacza "daję ci wartość i ta wartość to null", więc wartość domyślna jest pomijana. To zaskakuje osoby przychodzące z języków, w których null i undefined to to samo.

Czy wartość domyślna może korzystać z innego parametru?

Tak. Parametry są obliczane od lewej do prawej, więc wartość domyślna późniejszego parametru może używać wcześniejszych: function box(width, height = width). W wartości domyślnej możesz też wywoływać funkcje, na przykład function log(msg, time = Date.now()), a wyrażenie wykonuje się od nowa przy każdym wywołaniu.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ