Вгори та вниз: Створення калькулятора на JavaScript

Перша помилка: Велика суперечка про div

Все почалося з моєї амбітної спроби створити калькулятор. Мені знадобилася ціла година, щоб завершити фронтенд—так, ціла година!

ДИСКЛЕЙМЕР: На той момент я вже п’ять місяців вивчав фронтенд-розробку і був переконаний, що можу стати наступним великим веб-розробником. Спойлер: я не став.

Ось де я застряг. Я не міг зрозуміти, чому div калькулятора не хоче знаходитися під тегом h1. Я пильно дивився на код, як детектив, що розкриває справу, і лише пізніше зрозумів, що теги h1 за замовчуванням є блочними елементами.

pic

Навіть коли я намагався зробити їх інлайн, мій геніальний мозок забув про flex-direction: row, який був застосований до body. Рішення? Потрібно було змінити напрямок flex на column.
Ось і все! Успіх.

pic

Друга боротьба: Кнопки та дурниці в голові

Далі я взявся за те, щоб зробити кнопки функціональними. Я знав, як використовувати addEventListener (прослуховувач подій (Event Listener)), тому вирішив, що додавання inline onclick події безпосередньо в HTML не зашкодить. Це дозволило мені передавати функцію щоразу, коли кнопка натискалася. Все йшло добре.

Додати кнопку "Очистити все" — готово. Дуже просто. Просто стерти все на екрані. Я відчував себе непереможним.

Але потім з'явилася функція "Видалити останню цифру". Мій надмірно впевнений мозок сказав: “Пфф, це буде дуже легко.” Спойлер: це не було легко.
Моя перша спроба була настільки поганою, що будь-який досвідчений JavaScript-розробник сміявся б так сильно, що йому довелося б лягти на відпочинок.

Ось що я вважав геніальним, але насправді це була повна плутанина:

function number(x) {  
 box.value += x;  
 const clear = document.querySelector("#c");  
 clear.addEventListener("click", () => {  
 box.value = "";  
 });  
 const clr = document.querySelector("#x");  
 clr.addEventListener("click", () => {  
 box.value = Math.floor(box.value / 10);  
 });  
}

Пекло налагодження

Я натискаю “7”, і моя логіка успішно видаляє “7”. Але коли я намагався очистити наступну цифру, все очищалося. Я плакав всередині. Тоді я помітив, що функція виконувала математичну операцію постійно.
Чому?

Ми зможемо з'ясувати це за допомогою налагодження.

function number(x){  
 box.value+=x;  
 const clear=document.querySelector("#c")  
 clear.addEventListener("click",() => {  
 box.value=""  
 })  
 const clr=document.querySelector("#x")  
 clr.addEventListener("click",() => {  
 let remove=Math.floor(box.value / 10);  
 console.log("remove",remove)  
 console.log(box.value)  
 box.value=remove  
 })  
}

pic

За допомогою численних console.log я з’ясував, чому все очищалося, а на виході з’являлося 0. Причина була в тому, що прослуховувач події clear (Event Listener) був всередині функції number(), яка викликалася кожного разу, коли я натискав цифру. Помилка новачка.

Виправлення

Після кількох годин самозневажання та налагодження з допомогою console.log, я переписав логіку. Виявилося, що замість Math.floor потрібно було використовувати splice.
Ми пізніше побачимо, чому не слід було використовувати Math.floor, але поки що це працює чудово.

const clr = document.querySelector("#x");  
clr.addEventListener("click", () => {  
 if (box.value.length > 0) {  
 box.value = box.value.slice(0, -1);  
 console.log("Після видалення останньої цифри", box.value);  
 }  
});

Кнопка "Рівно": Зустрічайте всемогутній eval

Коли кнопки працювали правильно, наступним кроком було обробляти обчислення, коли натискається кнопка "=". Ось код:

function calculate() {  
 box.value = eval(box.value);  
}

Ура, це спрацювало! Я лягав спати, почувши себе справжнім JavaScript-магом.

Обробка помилок

Але зачекайте. Хороший програміст не просто йде, коли код працює. Потрібно перевіряти крайні випадки. А що, якщо ідіот (гмм, це я) введе 4+ і натисне "="? Бум. Нічого не відбувається. Тиша. Розчарування.

Ми не можемо залишити користувачів у такій ситуації. Їм потрібні підказки, навіть якщо вони такі ж недбалими, як я.
Вводимо обробку помилок.

Використовуючи простий блок try-catch, я додав спосіб обробляти некоректні введення:

function calculate() {  
 try {  
 box.value = eval(box.value);  
 } catch (e) {  
 box.value = "Введіть коректно, чувак. Що!?";  
 console.log(e);  
 }  
}

Тепер, якщо хтось введе нісенітницю типу 5/* і натисне "=", вони побачать дружнє повідомлення замість вічної тиші.

Ах, ці радощі від налагодження! Отже, я впевнено вирушив до проблеми "видалення останньої цифри", думаючи, що вже все зрозумів.

Все було добре до цього моменту, але для очищення останньої цифри Math.floor працював ідеально раніше, але що, якщо є оператори? Тоді все піде не за планом.

Детальне пояснення, чому замість Math.floor був використаний splice

Коли я ввів 6+6=12+23, як справжній геній програмування, я натиснув свою кнопку CLR, очікуючи, що маленьке 3 на кінці зникне. Але о ні! Що мене зустріло замість цього — математичний жах NaN.
Я витріщався на екран, ошелешений, як ніби сам калькулятор насміхався з мене.

Виявилось, що проблема не в моїй логіці — хоча ні, зачекайте, то була саме моя логіка. Суть була в тому, що мій геніальний Math.floor(box.value / 10) намагався виконати математичні операції зі рядком типу "12+23". Гарна новина: JavaScript не любить ділити рядки на числа. Результат? NaN.

Мій процес налагодження (або момент “Ага!”):

  1. Спочатку я п'ять хвилин дивився на екран, відмовляючись вірити.
  2. Потім я спробував додати кілька console.log як чарівний пил: console.log("remove", remove); console.log(box.value);
  3. І ось! Я зрозумів, що щоразу, коли я натискав CLR, математична операція намагалася зрозуміти "12+23" / 10. ВЕЛИКЕ НІ.
    Зрештою, мій мозок прошепотів: "Використовуй slice, дурню."

Виправлення:

Завдяки магії маніпулювання рядками, я замінив математичну операцію на магію slice:

const clr = document.querySelector("#x");  
clr.addEventListener("click", () =\> {  
 if (box.value.length > 0) {  
 box.value = box.value.slice(0, -1);  
 }  
});

Наслідки:

Я знову ввів 6+6=12+23. Натиснув CLR. 3 зникла. Натиснув знову. 2 зникла. Життя стало гарним. Мій калькулятор нарешті став нормальним інструментом, а не генератором образ.

Уроки, які я засвоїв: Американські гірки радості та розчарування

Створення цього калькулятора було поєднанням моментів “Ага!” і “О, чому ти мене ненавидиш?”. Але ось мої найбільші висновки:

  1. Фронтенд-дизайн: Зрозумій основи CSS перед тим, як починати. Не витрачай годину через flex-direction.
  2. Прослуховувачі подій (Event Listeners): Не вкладати їх там, де вони не потрібні. Функції повинні бути чистими та логічними.
    Простота - ключ: Іноді найкраще рішення - це найпростіше (привіт, slice()).
  3. Обробка помилок: Ніколи не припускайте, що користувачі будуть робити все правильно.

А в кінці, не забувайте сміятися з себе, коли все йде не за планом. Адже в кінці дня, ви навчаєтесь — і це найголовніше.

Тепер вибачте, я йду будувати гру хрестики-нулики з новоздобутою мудрістю.

Перекладено з: Ups and Downs of Making a Calculator in JavaScript

Leave a Reply

Your email address will not be published. Required fields are marked *