Усталені параметри
Усталені параметри функцій дають змогу ініціалізувати названі параметри усталеними значеннями, якщо значення не передано або передано undefined
.
Спробуйте його в дії
Синтаксис
function fnName(param1 = defaultValue1, /* …, */ paramN = defaultValueN) {
// …
}
Опис
У JavaScript параметри функцій усталено мають значення undefined
. Однак часто буває корисно встановити інше усталене значення. З цим допомагають усталені параметри.
У наступному прикладі, коли при виклику multiply
для b
не надано значення, то під час обчислення a * b
значення b
буде undefined
, і multiply
поверне NaN
.
function multiply(a, b) {
return a * b;
}
multiply(5, 2); // 10
multiply(5); // NaN !
Раніше загальноприйнята стратегія задання усталених значень полягала в перевірці параметрів у тілі функції та присвоєнні значення, якщо вони дорівнюють undefined
. У наступному прикладі b
отримує значення 1
, якщо multiply
викликається з лише одним аргументом:
function multiply(a, b) {
b = typeof b !== "undefined" ? b : 1;
return a * b;
}
multiply(5, 2); // 10
multiply(5); // 5
Завдяки усталеним параметрам перевірки в тілі функції більше не потрібні. Тепер можна призначити 1
як усталене значення для b
безпосередньо в заголовку функції:
function multiply(a, b = 1) {
return a * b;
}
multiply(5, 2); // 10
multiply(5); // 5
multiply(5, undefined); // 5
Параметри досі задаються зліва направо, перезаписуючи усталені параметри, навіть якщо наступні параметри не мають усталених значень.
function f(x = 1, y) {
return [x, y];
}
f(); // [1, undefined]
f(2); // [2, undefined]
[!NOTE] Перший усталений параметр і решта після нього не впливають на значення
length
(довжину) функції.
Усталені параметри існують у власній області видимості, яка є батьківською щодо області видимості, створеної для тіла функції.
Це означає, що на попередні параметри можна посилатися при визначенні наступних. Однак функції та змінні, оголошені в тілі функції, не слід використовувати при визначенні усталених значень; така спроба викличе помилку ReferenceError
під час виконання. Це також стосується змінних, оголошених у тілі функції за допомогою var
.
Наприклад, наступна функція викличе ReferenceError
під час виконання, оскільки усталене значення параметра a
не має доступу до області видимості тіла функції:
function f(a = go()) {
function go() {
return ":P";
}
}
f(); // ReferenceError: go is not defined
Ця функція виведе значення параметра a
, оскільки змінна var a
піднімається лише на початок області видимості, створеної для тіла функції, а не в батьківську область, створену для списку параметрів. Тому її значення невидиме для b
.
function f(a, b = () => console.log(a)) {
var a = 1;
b();
}
f(); // undefined
f(5); // 5
Усталені параметри можуть приймати будь-який вираз, але не можна використовувати await
або yield
, які призупиняють обчислення виразу. Параметр має бути визначений синхронно.
async function f(a = await Promise.resolve(1)) {
return a;
}
[!NOTE] Оскільки усталений параметр обчислюється під час виклику функції, а не під час її визначення, валідність операторів
await
таyield
залежить від поточної функції, а не від навколишньої. Наприклад, якщо поточна функція не єasync
, тодіawait
розглядатиметься як ідентифікатор, для якого застосовуються звичайні правила синтаксису ідентифікаторів, навіть якщо ця функція є вкладеною вasync
функцію.
Приклади
Передача undefined та інші хибні значення
У другому виклику цього прикладу, навіть попри те, що перший аргумент явно задано як undefined
(але не як null
або інші хибні значення), то значення аргументу num
все одно залишається усталеним.
function test(num = 1) {
console.log(typeof num);
}
test(); // 'number' (num дорівнює 1)
test(undefined); // 'number' (num також дорівнює 1)
// тест з іншими хибними значеннями:
test(""); // 'string' (num дорівнює '')
test(null); // 'object' (num дорівнює null)
Обчислення під час виклику
Усталений аргумент обчислюється під час виклику. На відміну від (наприклад) Python, новий об'єкт створюється кожного разу, коли функція викликається.
function append(value, array = []) {
array.push(value);
return array;
}
append(1); // [1]
append(2); // [2], не [1, 2]
Це стосується навіть функцій та змінних:
function callSomething(thing = something()) {
return thing;
}
let numberOfTimesCalled = 0;
function something() {
numberOfTimesCalled += 1;
return numberOfTimesCalled;
}
callSomething(); // 1
callSomething(); // 2
Попередні усталені параметри доступні для наступних
Параметри, визначені раніше (ліворуч), доступні для наступних усталених параметрів:
function greet(name, greeting, message = `${greeting}, ${name}`) {
return [name, greeting, message];
}
greet("Дмитро", "Привіт"); // ["Дмитро", "Привіт", "Привіт, Дмитро"]
greet("Дмитро", "Привіт", "З Днем Народження!"); // ["Дмитро", "Привіт", "З Днем Народження!"]
Щоб продемонструвати, як обробляються різні крайові випадки, цю функціональність можна відтворити таким чином:
function go() {
return ":P";
}
function withDefaults(
a,
b = 5,
c = b,
d = go(),
e = this,
f = arguments,
g = this.value,
) {
return [a, b, c, d, e, f, g];
}
function withoutDefaults(a, b, c, d, e, f, g) {
switch (arguments.length) {
case 0:
case 1:
b = 5;
case 2:
c = b;
case 3:
d = go();
case 4:
e = this;
case 5:
f = arguments;
case 6:
g = this.value;
}
return [a, b, c, d, e, f, g];
}
withDefaults.call({ value: "=^_^=" });
// [undefined, 5, 5, ":P", {value:"=^_^="}, arguments, "=^_^="]
withoutDefaults.call({ value: "=^_^=" });
// [undefined, 5, 5, ":P", {value:"=^_^="}, arguments, "=^_^="]
Деструктурований параметр із присвоєнням усталеного значення
Для присвоєння усталеного значення можна скористатися синтаксисом присвоєння з деструктуруванням.
Загальноприйнятим підходом є задання порожнього об'єкта або масиву як усталеного значення для деструктурованого параметра; наприклад: [x = 1, y = 2] = []
. Це дає змогу не передавати нічого у функцію і все одно отримати ці значення заповненими заздалегідь:
function preFilledArray([x = 1, y = 2] = []) {
return x + y;
}
preFilledArray(); // 3
preFilledArray([]); // 3
preFilledArray([2]); // 4
preFilledArray([2, 3]); // 5
// Аналогічно працює для об'єктів:
function preFilledObject({ z = 3 } = {}) {
return z;
}
preFilledObject(); // 3
preFilledObject({}); // 3
preFilledObject({ z: 2 }); // 2
Специфікації
Сумісність із браузерами
desktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Default parameters
|
Chrome Full support 49 | Edge Full support 14 | Firefox Full support 15 | Internet Explorer No support Ні | Opera Full support 36 | Safari Full support 10 | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox for Android Full support 15 | Opera Android Full support 36 | Safari on iOS Full support 10 | Samsung Internet Full support 5.0 | Deno Full support 1.0 | Node.js Full support 6.0.0 |
Destructured parameter with default value assignment
|
Chrome Full support 49 | Edge Full support 14 | Firefox Full support 41 | Internet Explorer No support Ні | Opera Full support 36 | Safari Full support 10 | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox for Android Full support 41 | Opera Android Full support 36 | Safari on iOS Full support 10 | Samsung Internet Full support 5.0 | Deno Full support 1.0 | Node.js Full support 6.0.0 |
Parameters without defaults after default parameters
|
Chrome Full support 49 | Edge Full support 14 | Firefox Full support 26 | Internet Explorer No support Ні | Opera Full support 36 | Safari Full support 10 | WebView Android Full support 49 | Chrome Android Full support 49 | Firefox for Android Full support 26 | Opera Android Full support 36 | Safari on iOS Full support 10 | Samsung Internet Full support 5.0 | Deno Full support 1.0 | Node.js Full support 6.0.0 |