Към съдържанието
wannacode

Стойности по подразбиране

Проблем

Две покупки, три покупки

Касата трябва да сумира цените на покупките. Понякога са две, понякога три. Функцията е една и съща по смисъл: „сумирай“. В 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));
Изход
8
NaN

С три аргумента работи. С два програмата не спира, а печата NaN („not a number“, „не е число“). Значи и с два аргумента се вика функцията с трите параметъра. Къде отиде първата?

Идеята

Едно име, една функция

В JavaScript всяка function се записва под името си, преди да тръгне първият ред. Ако две се казват еднакво, втората замества първата, пак преди първия ред. Затова и първото извикване стига до втората функция.

Затова JavaScript няма претоварване (overloading): две функции с едно име, които се различават по параметрите, както в Java и C#. Вместо това една функция може да приема различен брой аргументи. Как, ще видиш в следващите карти.

function printHeader() {
console.log("Квартален магазин");
}
printHeader();
function printHeader() {
console.log("Магазин „Център“");
}
printHeader();
Стъпка по стъпка, с думи
  1. Преди да изпълни и един ред, JavaScript записва всяка function. Името printHeader сочи първата.
  2. Пак преди първия ред: втората function със същото име. Името вече сочи нея, а първата я няма.
  3. Чак сега тръгва първият ред. Извикването стига до втората функция: „Магазин „Център““.
  4. Второто извикване: пак „Магазин „Център““.
  5. Името е едно, а последната 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);
Отговор

Идеята

Стойност по подразбиране

Една функция стига и за две, и за три покупки. Дай на третия параметър стойност по подразбиране: тя се ползва, когато аргументът не е подаден.

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.5
8

c = 0 значи: ако при извикването има само два аргумента, c е 0. Ако има три, c е третият.

Параметрите със стойност по подразбиране се пишат след тези без такава. Аргументите се свързват с параметрите по място, затова незадължителните стоят накрая.

По-точно, за любопитните

Стойността по подразбиране се смята при всяко извикване, в което аргументът липсва. Затова масив по подразбиране е нов всеки път:

function addItem(item, cart = []) {
cart.push(item);
return cart;
}
console.log(addItem("хляб"));
console.log(addItem("мляко"));
Изход
[ 'хляб' ]
[ 'мляко' ]

Пробвай

Намери грешката

Програмата тръгва, но печата „undefined, нощувки: Мария“. На кой ред е грешката?

Избери реда с грешката.

Идеята

Как се пропуска параметър

Хотелът записва резервации. Една нощувка без закуска е най-честата, затова двете са по подразбиране:

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());
Изход
11
9.99
0

Трите точки пред името (...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;
}

Упражнение

Една функция вместо няколко

1. Най-голямото. Напиши една функция largest(...numbers), която връща най-голямото от колкото и да е числа.

Извикване
largest(3, 8)
largest(4, 9, 2)
largest(2.5, 1.5)
Изход
8
9
2.5

2. Среден успех. Функция average(...grades) връща средното на произволен брой оценки, а без оценки връща 0.

Извикване
average(5, 6, 4)
average(6, 5)
average()
Изход
5
5.5
0

3. Ред от бележката. printLine(item, qty) печата „Кафе x 2“. Направи бройката незадължителна: без нея е 1.

Извикване
printLine("Кафе", 2)
printLine("Кроасан")
Изход
Кафе x 2
Кроасан x 1

4. Безплатна доставка. shippingCost(total, freeFrom = 50) връща 0, ако поръчката е поне колкото прага, иначе 4,99 €. Прагът е 50 €, ако не е подаден друг.

Извикване
shippingCost(62.0)
shippingCost(30.0)
shippingCost(30.0, 25)
Изход
0
4.99
0

Тест

Провери се

1. Във файла има function total(a, b) { … } и под нея function total(a, b, c) { … }. Какво дава total(2, 3)?
2. function total(a, b, c = 0) { return a + b + c; } Какво връща total(2, 3)?
3. Как се извиква function book(name, nights = 1, breakfast = false), за да има закуска, а нощувките да останат 1?
4. Какво е prices вътре в function total(...prices)?
5. Коя програма върви без грешка, но печата грешен резултат?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·