← Вернуться к урокам

⚡ JavaScript логика калькулятора

Урок 3 из 5

🎯 Цель урока

В этом уроке мы оживим наш калькулятор с помощью JavaScript! Научимся обрабатывать нажатия кнопок, выполнять математические операции и управлять отображением. Создадим полнофункциональный калькулятор с обработкой ошибок.

💡 Что вы узнаете:

• Переменные и управление состоянием
• Функции для математических операций
• Обработку событий и DOM манипуляции
• Работу с eval() и обработку ошибок
• Логику калькулятора и пользовательский ввод

📚 JavaScript концепции

let и const

Переменные для хранения состояния калькулятора. let - изменяемые, const - константы

function

Функции для выполнения математических операций и управления интерфейсом

document.getElementById()

Получение доступа к HTML элементам для изменения их содержимого

eval()

Выполнение математических выражений из строки. Осторожно - может быть опасно!

try...catch

Обработка ошибок для предотвращения "поломки" приложения

🔧 Переменные состояния

Начнём с создания переменных для хранения состояния калькулятора:

// Переменные для калькулятора
let calcDisplay = '0';
let shouldResetDisplay = false;
let currentMode = 'calc'; // 'calc' или 'quest'

// Получаем ссылки на HTML элементы
const displayElement = document.getElementById('calcDisplay');
const calculatorSection = document.getElementById('calculator-section');
const questSection = document.getElementById('quest-section');
Состояние приложения

calcDisplay хранит то, что показывается на экране. shouldResetDisplay определяет, нужно ли очистить дисплей при следующем вводе

🔢 Функции работы с числами

Создаём функцию для добавления цифр и операторов:

function appendToCalc(value) {
    // Если нужно сбросить дисплей после вычисления
    if (shouldResetDisplay) {
        calcDisplay = '';
        shouldResetDisplay = false;
    }
    
    // Если дисплей показывает '0' и вводим не точку
    if (calcDisplay === '0' && value !== '.') {
        calcDisplay = value;
    } else {
        calcDisplay += value;
    }
    
    // Обновляем отображение на экране
    updateCalcDisplay();
}

function updateCalcDisplay() {
    displayElement.textContent = calcDisplay;
}

🔍 Логика функции:

• Проверяем, нужно ли сбросить дисплей
• Заменяем '0' на новую цифру или добавляем к существующему числу
• Обновляем HTML элемент дисплея
• Сбрасываем флаг reset после использования

🧹 Функции очистки

Создаём функции для очистки и удаления символов:

function clearCalc() {
    calcDisplay = '0';
    shouldResetDisplay = false;
    updateCalcDisplay();
}

function deleteLast() {
    // Если на дисплее только один символ или '0'
    if (calcDisplay.length <= 1 || calcDisplay === '0') {
        calcDisplay = '0';
    } else {
        // Удаляем последний символ
        calcDisplay = calcDisplay.slice(0, -1);
    }
    
    updateCalcDisplay();
}
slice(0, -1)

Метод slice удаляет последний символ из строки. 0 - начало, -1 - предпоследний символ

🧮 Вычисление результата

Самая важная функция - выполнение математических операций:

function calculateResult() {
    try {
        // Заменяем символ умножения для eval()
        let expression = calcDisplay.replace(/×/g, '*');
        
        // Проверяем, что выражение не пустое
        if (!expression || expression === '0') {
            return;
        }
        
        // Вычисляем результат
        let result = eval(expression);
        
        // Проверяем на деление на ноль
        if (!isFinite(result)) {
            calcDisplay = 'Ошибка';
            shouldResetDisplay = true;
            updateCalcDisplay();
            return;
        }
        
        // Округляем до 10 знаков после запятой
        result = Math.round(result * 10000000000) / 10000000000;
        
        calcDisplay = result.toString();
        shouldResetDisplay = true;
        updateCalcDisplay();
        
    } catch (error) {
        // Обрабатываем ошибки вычисления
        calcDisplay = 'Ошибка';
        shouldResetDisplay = true;
        updateCalcDisplay();
    }
}

⚠️ Безопасность eval():

• eval() выполняет любой JavaScript код, что может быть опасно
• Мы используем его только для математических выражений
• В реальных проектах лучше использовать специальные библиотеки
• try...catch защищает от ошибок выполнения

🎮 Переключение режимов

Функция для переключения между калькулятором и квестами:

function setMode(mode) {
    currentMode = mode;
    
    // Удаляем класс active у всех кнопок
    document.querySelectorAll('.mode-btn').forEach(btn => {
        btn.classList.remove('active');
    });
    
    // Добавляем класс active к нажатой кнопке
    document.getElementById(mode + '-mode').classList.add('active');
    
    // Показываем/скрываем соответствующие секции
    if (mode === 'quest') {
        questSection.style.display = 'block';
        calculatorSection.style.display = 'none';
    } else {
        questSection.style.display = 'none';
        calculatorSection.style.display = 'block';
    }
}
querySelectorAll()

Находит все элементы с указанным селектором. forEach() применяет функцию к каждому найденному элементу

⌨️ Поддержка клавиатуры

Добавим возможность использовать клавиатуру для ввода:

// Обработка нажатий клавиш
document.addEventListener('keydown', function(event) {
    // Только если активен режим калькулятора
    if (currentMode !== 'calc') return;
    
    const key = event.key;
    
    // Обрабатываем цифры
    if ('0123456789'.includes(key)) {
        appendToCalc(key);
    }
    // Обрабатываем операторы
    else if ('+-*/'.includes(key)) {
        const operator = key === '*' ? '×' : key;
        appendToCalc(operator);
    }
    // Обрабатываем точку
    else if (key === '.') {
        appendToCalc('.');
    }
    // Enter или = для вычисления
    else if (key === 'Enter' || key === '=') {
        event.preventDefault();
        calculateResult();
    }
    // Backspace для удаления
    else if (key === 'Backspace') {
        event.preventDefault();
        deleteLast();
    }
    // Escape для очистки
    else if (key === 'Escape') {
        clearCalc();
    }
});

🎮 Интерактивная демонстрация

Попробуй наш работающий калькулятор прямо здесь:

🧮 Рабочий калькулятор

0

Попробуй вычислить: 15 × 4 + 8 🧮

🔧 Инициализация приложения

Код для запуска приложения при загрузке страницы:

// Инициализация при загрузке страницы
document.addEventListener('DOMContentLoaded', function() {
    // Устанавливаем начальный режим
    setMode('quest');
    
    // Обновляем дисплей калькулятора
    updateCalcDisplay();
    
    // Добавляем эффекты при загрузке
    document.querySelector('.game-container').style.opacity = '0';
    setTimeout(() => {
        document.querySelector('.game-container').style.transition = 'opacity 0.5s';
        document.querySelector('.game-container').style.opacity = '1';
    }, 100);
    
    console.log('🧮 Математическое приложение загружено!');
});
DOMContentLoaded

Событие, которое срабатывает когда HTML полностью загружен. Лучшее место для инициализации JavaScript

🐛 Обработка ошибок

Добавим более детальную обработку различных ошибок:

function safeCalculate(expression) {
    // Проверяем на пустое выражение
    if (!expression || expression.trim() === '') {
        return { error: 'Пустое выражение' };
    }
    
    // Проверяем на недопустимые символы
    const allowedChars = /^[0-9+\-*/().×\s]+$/;
    if (!allowedChars.test(expression)) {
        return { error: 'Недопустимые символы' };
    }
    
    // Проверяем на последовательные операторы
    if (/[+\-*/×]{2,}/.test(expression)) {
        return { error: 'Неправильное выражение' };
    }
    
    try {
        const cleanExpression = expression.replace(/×/g, '*');
        const result = eval(cleanExpression);
        
        if (!isFinite(result)) {
            return { error: 'Деление на ноль' };
        }
        
        return { result: result };
    } catch (error) {
        return { error: 'Ошибка вычисления' };
    }
}

🎓 Итоги урока

  • Переменные: Научились управлять состоянием калькулятора
  • Функции: Создали модульную архитектуру кода
  • DOM: Научились изменять содержимое HTML элементов
  • События: Обрабатываем клики мыши и нажатия клавиш
  • Математика: Выполняем вычисления с помощью eval()
  • Ошибки: Предотвращаем "поломку" приложения

🚀 Что дальше?

В следующем уроке мы создадим систему математических квестов с разными уровнями сложности, статистикой и системой очков для геймификации обучения!