Стойности по подразбиране
Проблем
Две покупки, три покупки
Касата трябва да сумира цените на покупките. Понякога са две, понякога три. Функцията е една и съща по смисъл: „сумирай“. В Java и C# това се прави с два метода с едно име и различен брой параметри. Пробваш същото:
function total(a, b) { return a + b;}
function total(a, b, c) { return a + b + c;}
console.log(total(2.5, 4.0, 1.5));console.log(total(2.5, 4.0));8NaNС три аргумента работи. С два програмата не спира, а печата NaN („not a number“, „не е число“). Значи и с два аргумента се вика функцията с трите параметъра. Къде отиде първата?
Идеята
Едно име, една функция
В JavaScript всяка function се записва под името си, преди да тръгне първият ред. Ако две се казват еднакво, втората замества първата, пак преди първия ред. Затова и първото извикване стига до втората функция.
Затова JavaScript няма претоварване (overloading): две функции с едно име, които се различават по параметрите, както в Java и C#. Вместо това една функция може да приема различен брой аргументи. Как, ще видиш в следващите карти.
function printHeader() { console.log("Квартален магазин");}
printHeader();
function printHeader() { console.log("Магазин „Център“");}
printHeader();Стъпка по стъпка, с думи
- Преди да изпълни и един ред, JavaScript записва всяка function. Името printHeader сочи първата.
- Пак преди първия ред: втората function със същото име. Името вече сочи нея, а първата я няма.
- Чак сега тръгва първият ред. Извикването стига до втората функция: „Магазин „Център““.
- Второто извикване: пак „Магазин „Център““.
- Името е едно, а последната function печели. Затова и първото извикване печата новата бележка.
По-точно, за любопитните
Ако във файла има import (както в програмите, които четат от клавиатурата), Node.js го пуска като модул. Там две function с едно име са грешка и програмата не тръгва:
SyntaxError: Identifier 'total' has already been declaredТова е по-добре: грешката се вижда веднага, вместо тихо да се вика друга функция.
Пробвай
Коя функция?
Какво ще отпечата програмата?
function describe(x) { console.log(`цяло: ${x}`);}
function describe(x) { console.log(`дробно: ${x}`);}
describe(5);describe(5.0);describe е заместила първата, затова и двете извиквания стигат до „дробно“. А 5.0 в JavaScript е просто 5: целите и дробните числа са един тип, number.Идеята
Стойност по подразбиране
Една функция стига и за две, и за три покупки. Дай на третия параметър стойност по подразбиране: тя се ползва, когато аргументът не е подаден.
function total(a, b, c = 0) { return a + b + c;}
console.log(total(2.5, 4.0));console.log(total(2.5, 4.0, 1.5));6.58c = 0 значи: ако при извикването има само два аргумента, c е 0. Ако има три, c е третият.
Параметрите със стойност по подразбиране се пишат след тези без такава. Аргументите се свързват с параметрите по място, затова незадължителните стоят накрая.
По-точно, за любопитните
Стойността по подразбиране се смята при всяко извикване, в което аргументът липсва. Затова масив по подразбиране е нов всеки път:
function addItem(item, cart = []) { cart.push(item); return cart;}
console.log(addItem("хляб"));console.log(addItem("мляко"));[ 'хляб' ][ 'мляко' ]Пробвай
Намери грешката
Избери реда с грешката.
nights = 1) е преди параметъра без такава (name). JavaScript го позволява, но аргументите се свързват по място: "Мария" отива в nights, а name остава undefined. Поправката е function book(name, nights = 1).Идеята
Как се пропуска параметър
Хотелът записва резервации. Една нощувка без закуска е най-честата, затова двете са по подразбиране:
function book(name, nights = 1, breakfast = false) { console.log(`${name}, нощувки: ${nights}`); if (breakfast) { console.log(" със закуска"); }}
book("Мария");book("Иван", 3);book("Петя", undefined, true);Мария, нощувки: 1Иван, нощувки: 3Петя, нощувки: 1 със закускаПетя иска закуска, но една нощувка. В JavaScript аргументи по име няма: аргументите отиват в параметрите само по място. За да стигнеш до третия, подаваш на мястото на втория undefined. Само undefined задейства стойността по подразбиране. null не я задейства:
book("Петя", null);Петя, нощувки: nullПо-точно, за любопитните
Когато незадължителните параметри са много, в JavaScript обикновено се подава обект с имена: { breakfast: true }. Във функцията { nights = 1, breakfast = false } = {} взима всяка стойност по име, със стойност по подразбиране. Обектите ще разгледаме в модул „Класове и обекти“, но шаблонът е толкова чест, че е добре да го познаеш:
function book(name, { nights = 1, breakfast = false } = {}) { console.log(`${name}, нощувки: ${nights}`); if (breakfast) { console.log(" със закуска"); }}
book("Мария");book("Петя", { breakfast: true });book("Георги", { nights: 2 });Мария, нощувки: 1Петя, нощувки: 1 със закускаГеорги, нощувки: 2Идеята
Колкото искаш аргументи
А ако покупките са пет? Двайсет? Не пишеш параметър за всяка. Казваш, че функцията приема произволен брой аргументи:
function total(...prices) { let result = 0; for (const p of prices) { result += p; } return result;}
console.log(total(1.5, 2.0, 3.5, 4.0));console.log(total(9.99));console.log(total());119.990Трите точки пред името (...prices) значат: „подай колкото искаш стойности“. Вътре във функцията те пристигат като масив, който може да е и празен. Това се казва rest параметър.
function show(...prices) { console.log(prices);}
show(1.5, 2.0);[ 1.5, 2 ]Затова и console.log печата колкото стойности му дадеш: това е една функция, която приема произволен брой аргументи.
console.log("Хляб", "Мляко", "Кафе");console.log(Math.max(3, 8, 2));Хляб Мляко Кафе8По-точно, за любопитните
- Такъв параметър може да е само един и трябва да е последен:
function receipt(title, ...prices).
Пробвай
Какво липсва?
function total(prices) {
let result = 0;
for (const p of prices) {
result += p;
}
return result;
}...prices: трите точки пред името събират всички аргументи в масив.Упражнение
Една функция вместо няколко
1. Най-голямото. Напиши една функция largest(...numbers), която връща най-голямото от колкото и да е числа.
largest(3, 8)largest(4, 9, 2)largest(2.5, 1.5)892.52. Среден успех. Функция average(...grades) връща средното на произволен брой оценки, а без оценки връща 0.
average(5, 6, 4)average(6, 5)average()55.503. Ред от бележката. printLine(item, qty) печата „Кафе x 2“. Направи бройката незадължителна: без нея е 1.
printLine("Кафе", 2)printLine("Кроасан")Кафе x 2Кроасан x 14. Безплатна доставка. shippingCost(total, freeFrom = 50) връща 0, ако поръчката е поне колкото прага, иначе 4,99 €. Прагът е 50 €, ако не е подаден друг.
shippingCost(62.0)shippingCost(30.0)shippingCost(30.0, 25)04.990Тест