Перейти к основному содержимому

Практика

Разработчику Архитектору

Практика

Продолжаем работу с калькулятором

Практическое задание
Выполните нижеуказанное задание.

Настало время небольшой практики. Вернёмся к нашему проекту - калькулятор на HTML, и в файле script.js реализуем логику калькулятора:

  • создайте новый файл script.js;
  • получите элементы из DOM-дерева и определите их как переменные (или константы);
  • добавьте обработку кнопок через цикл - сделайте проверку на текст кнопки;
  • добавьте переменные (или константы) a и b для чисел-операндов;
  • не забудьте добавить проверку деления на 0.

Добавьте в HTML связь со скриптом:

<script src="script.js"></script>

Вот пример простейшего скрипта для нас:

const num1 = document.getElementById('num1');
const num2 = document.getElementById('num2');
const result = document.getElementById('result');
const error = document.getElementById('error');
const buttons = document.querySelectorAll('.buttons button');
const equals = document.querySelector('.equals');

let operation = null;

buttons.forEach(button => {
button.addEventListener('click', () => {
operation = button.textContent;
});
});

equals.addEventListener('click', () => {
const a = Number(num1.value);
const b = Number(num2.value);

if (!operation) {
error.textContent = 'Выберите операцию';
return;
}

let res;
switch(operation) {
case '+': res = a + b; break;
case '-': res = a - b; break;
case '×': res = a * b; break;
case '÷': res = b !== 0 ? a / b : 'Ошибка';
}

result.textContent = res === 'Ошибка' ? res : res.toFixed(2);
error.textContent = res === 'Ошибка' ? 'Деление на ноль' : '';
});

Итоговая логика будет такая:

  1. указывается первое и второе число (операнды);
  2. выбирается операция;
  3. запрашивается результат;
  4. выполняется вычисление и результат выводится:

image-14.png

Можете разбавить проект своей дополнительной логикой и вычислениями.


Полезные JavaScript-сниппеты для повседневной практики

Ниже приведена подборка универсальных и часто используемых фрагментов кода на JavaScript. Эти сниппеты подходят как для начинающих, так и для опытных разработчиков.

Получение параметров из URL

const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('user_id');
const theme = urlParams.get('theme') || 'light';

Этот код извлекает значения GET-параметров из адресной строки. Если параметр отсутствует, можно задать значение по умолчанию.


Проверка типа данных

function isString(value) {
return typeof value === 'string';
}

function isArray(value) {
return Array.isArray(value);
}

function isObject(value) {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}

function isFunction(value) {
return typeof value === 'function';
}

Такие функции помогают безопасно определять тип переменной перед выполнением операций.


Проверка на null и undefined

function isNullish(value) {
return value === null || value === undefined;
}

// Или с использованием оператора нулевого слияния (для значений по умолчанию)
const name = inputName ?? 'Гость';

Полезно при валидации входных данных или конфигураций.


Генерация уникального ID

function generateId() {
return Date.now().toString(36) + Math.random().toString(36).substring(2);
}

Простой способ создать уникальную строку без использования сторонних библиотек. Подходит для временных идентификаторов.


Создание DOM-элемента

function createElement(tag, attributes = {}, children = []) {
const element = document.createElement(tag);
Object.entries(attributes).forEach(([key, value]) => {
element.setAttribute(key, value);
});
children.forEach(child => {
if (typeof child === 'string') {
element.appendChild(document.createTextNode(child));
} else {
element.appendChild(child);
}
});
return element;
}

// Пример использования:
const button = createElement('button', { class: 'btn primary' }, ['Нажми меня']);
document.body.appendChild(button);

Упрощает динамическое создание интерфейсов без шаблонных строк.


Копирование текста в буфер обмена

async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
console.log('Скопировано в буфер обмена');
} catch (err) {
console.error('Не удалось скопировать:', err);
}
}

Современный способ копирования, работающий в большинстве браузеров. Требует HTTPS или локального хоста.


Ожидание (задержка)

function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

// Пример использования:
await wait(1000); // Пауза на 1 секунду

Полезно при имитации загрузки, анимациях или тестировании асинхронных операций.


Форматирование даты

function formatDate(date, locale = 'ru-RU') {
return new Intl.DateTimeFormat(locale, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}).format(date);
}

// Пример:
console.log(formatDate(new Date())); // "18 марта 2026 г., 14:30"

Использует встроенный API Intl для локализованного формата без внешних зависимостей.


Работа с массивами: создание списков

// Создание списка чисел от start до end
function range(start, end) {
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
}

// Пример:
console.log(range(1, 5)); // [1, 2, 3, 4, 5]

Удобно для генерации тестовых данных или заполнения выпадающих списков.


Создание объекта из пар ключ-значение

function createObject(keys, values) {
const obj = {};
keys.forEach((key, index) => {
obj[key] = values[index];
});
return obj;
}

// Или через Object.fromEntries:
const obj = Object.fromEntries([
['name', 'Алиса'],
['age', 30]
]);

Полезно при преобразовании данных из форм или API-ответов.


Работа с промисами: выполнение всех или любого

// Все промисы должны завершиться успешно
Promise.all([fetch('/api/user'), fetch('/api/profile')])
.then(responses => Promise.all(responses.map(r => r.json())))
.then(data => console.log(data));

// Достаточно одного успешного
Promise.any([fetch('/mirror1/data'), fetch('/mirror2/data')])
.then(response => response.json())
.then(data => console.log('Получено:', data));

Promise.all — для строгой последовательности, Promise.any — для отказоустойчивых запросов.


Циклы: итерация по объекту

const user = { name: 'Борис', age: 28, city: 'Казань' };

// Только собственные перечисляемые свойства
for (const key in user) {
if (Object.hasOwn(user, key)) {
console.log(`${key}: ${user[key]}`);
}
}

// Или через Object.entries:
Object.entries(user).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});

Безопасный способ обхода объектов без наследуемых свойств.


Тестирование: простая функция assert

function assert(condition, message = 'Assertion failed') {
if (!condition) {
throw new Error(message);
}
}

// Пример:
assert(typeof calculate(2, 3) === 'number', 'calculate должен возвращать число');

Минималистичная замена полноценным тестовым фреймворкам для быстрой проверки логики.


Обработка ошибок в асинхронных функциях

async function safeFetch(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('Ошибка запроса:', error.message);
return null;
}
}

Обеспечивает устойчивость к сетевым сбоям и некорректным ответам сервера.