Приведи примеры задач которые делаешь на JavaScript
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Примеры типовых задач на JavaScript в Frontend-разработке
Как Frontend Developer с 10+ лет опыта, я решаю широкий спектр задач — от простой манипуляции DOM до создания сложных SPA-приложений. Вот ключевые категории с примерами:
1. Манипуляция DOM и работа с событиями
Цель: Динамическое изменение контента и обработка пользовательских взаимодействий.
// Пример: Создание интерактивного списка задач (To-Do)
class TodoList {
constructor(containerId) {
this.container = document.getElementById(containerId);
this.tasks = [];
this.init();
}
init() {
this.renderForm();
this.container.addEventListener('click', (e) => {
if (e.target.classList.contains('delete-btn')) {
this.deleteTask(e.target.dataset.id);
}
});
}
renderForm() {
const form = document.createElement('form');
form.innerHTML = `
<input type="text" class="task-input" placeholder="Новая задача">
<button type="submit">Добавить</button>
`;
form.addEventListener('submit', (e) => {
e.preventDefault();
const input = form.querySelector('.task-input');
if (input.value.trim()) {
this.addTask(input.value.trim());
input.value = '';
}
});
this.container.appendChild(form);
}
addTask(text) {
const task = { id: Date.now(), text, completed: false };
this.tasks.push(task);
this.renderTasks();
}
deleteTask(id) {
this.tasks = this.tasks.filter(task => task.id !== Number(id));
this.renderTasks();
}
renderTasks() {
const list = this.container.querySelector('.task-list') || document.createElement('ul');
list.className = 'task-list';
list.innerHTML = this.tasks.map(task => `
<li>
${task.text}
<button class="delete-btn" data-id="${task.id}">Удалить</button>
</li>
`).join('');
if (!this.container.querySelector('.task-list')) {
this.container.appendChild(list);
}
}
}
// Использование
new TodoList('todo-container');
2. Работа с API и асинхронными операциями
Цель: Получение, отправка данных и обработка асинхронных сценариев.
// Пример: Загрузка и отображение данных с внешнего API
async function loadUserData(userId) {
try {
// Используем Promise.all для параллельных запросов
const [userResponse, postsResponse] = await Promise.all([
fetch(`https://jsonplaceholder.typicode.com/users/${userId}`),
fetch(`https://jsonplaceholder.typicode.com/users/${userId}/posts`)
]);
if (!userResponse.ok || !postsResponse.ok) {
throw new Error('Ошибка загрузки данных');
}
const user = await userResponse.json();
const posts = await postsResponse.json();
return { user, posts };
} catch (error) {
console.error('Произошла ошибка:', error);
// Можно добавить повторные попытки или fallback-логику
return { user: null, posts: [], error: error.message };
}
}
// Использование с современным синтаксисом
const displayData = async (userId) => {
const { user, posts, error } = await loadUserData(userId);
if (error) {
document.getElementById('content').innerHTML = `
<div class="error">Ошибка: ${error}</div>
`;
return;
}
document.getElementById('content').innerHTML = `
<h2>${user.name}</h2>
<p>Email: ${user.email}</p>
<h3>Посты (${posts.length}):</h3>
<ul>
${posts.map(post => `<li><strong>${post.title}</strong>: ${post.body}</li>`).join('')}
</ul>
`;
};
// Пример с debounce для поиска
function createSearchInput(apiEndpoint) {
let timeoutId;
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', (e) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(async () => {
const results = await searchData(apiEndpoint, e.target.value);
updateResultsUI(results);
}, 300); // Задержка 300мс
});
}
3. Состояние приложения и управление данными
Цель: Создание предсказуемого состояния в сложных интерфейсах.
// Пример: Простой менеджер состояния (State Manager)
class StateManager {
constructor(initialState = {}) {
this.state = initialState;
this.listeners = [];
this.actions = {};
}
subscribe(listener) {
this.listeners.push(listener);
return () => {
this.listeners = this.listeners.filter(l => l !== listener);
};
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.notifyListeners();
}
notifyListeners() {
this.listeners.forEach(listener => listener(this.state));
}
registerAction(name, action) {
this.actions[name] = (payload) => {
const newState = action(this.state, payload);
this.setState(newState);
};
}
dispatch(actionName, payload) {
if (this.actions[actionName]) {
this.actions[actionName](payload);
}
}
}
// Использование
const store = new StateManager({
user: null,
cart: [],
isAuthenticated: false
});
// Регистрируем actions
store.registerAction('ADD_TO_CART', (state, product) => ({
...state,
cart: [...state.cart, product]
}));
store.registerAction('LOGIN', (state, user) => ({
...state,
user,
isAuthenticated: true
}));
// Подписываемся на изменения
const unsubscribe = store.subscribe((state) => {
console.log('Состояние обновлено:', state);
updateUI(state);
});
// Диспатчим actions
store.dispatch('LOGIN', { name: 'Иван', email: 'ivan@example.com' });
store.dispatch('ADD_TO_CART', { id: 1, name: 'Ноутбук', price: 999 });
4. Оптимизация производительности
Цель: Улучшение скорости загрузки и отзывчивости интерфейса.
// Пример: Ленивая загрузка изображений (Lazy Loading)
class LazyLoader {
constructor() {
this.images = document.querySelectorAll('img[data-src]');
this.observer = null;
this.init();
}
init() {
if ('IntersectionObserver' in window) {
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadImage(entry.target);
this.observer.unobserve(entry.target);
}
});
}, {
rootMargin: '50px 0px',
threshold: 0.01
});
this.images.forEach(img => this.observer.observe(img));
} else {
// Fallback для старых браузеров
this.loadImagesFallback();
}
}
loadImage(img) {
img.src = img.dataset.src;
img.onload = () => {
img.removeAttribute('data-src');
img.classList.add('loaded');
};
}
loadImagesFallback() {
this.images.forEach(img => {
if (this.isInViewport(img)) {
this.loadImage(img);
}
});
// Дебаунс для scroll события
let scrollTimeout;
window.addEventListener('scroll', () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
this.images.forEach(img => {
if (img.hasAttribute('data-src') && this.isInViewport(img)) {
this.loadImage(img);
}
});
}, 100);
});
}
isInViewport(element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
}
// Инициализация при загрузке страницы
document.addEventListener('DOMContentLoaded', () => new LazyLoader());
5. Работа с формами и валидация
Цель: Создание удобных, безопасных и отзывчивых форм.
// Пример: Комплексная валидация формы
class FormValidator {
constructor(formId, config) {
this.form = document.getElementById(formId);
this.config = config;
this.errors = new Set();
this.init();
}
init() {
this.form.addEventListener('submit', (e) => this.handleSubmit(e));
// Валидация в реальном времени
Object.keys(this.config.fields).forEach(fieldName => {
const field = this.form.querySelector(`[name="${fieldName}"]`);
if (field) {
field.addEventListener('blur', () => this.validateField(fieldName));
field.addEventListener('input', () => {
if (this.errors.has(fieldName)) {
this.validateField(fieldName);
}
});
}
});
}
validateField(fieldName) {
const field = this.form.querySelector(`[name="${fieldName}"]`);
const rules = this.config.fields[fieldName];
const value = field.value.trim();
const errorElement = this.getErrorElement(field);
// Очищаем предыдущие ошибки
this.clearFieldError(fieldName);
for (const rule of rules) {
const isValid = this.checkRule(rule, value);
if (!isValid) {
this.errors.add(fieldName);
this.showError(field, errorElement, rule.message);
return false;
}
}
this.errors.delete(fieldName);
this.showSuccess(field, errorElement);
return true;
}
checkRule(rule, value) {
switch (rule.type) {
case 'required':
return value.length > 0;
case 'minLength':
return value.length >= rule.value;
case 'maxLength':
return value.length <= rule.value;
case 'pattern':
return rule.value.test(value);
case 'custom':
return rule.validate(value);
default:
return true;
}
}
handleSubmit(e) {
e.preventDefault();
// Валидируем все поля
let isValid = true;
Object.keys(this.config.fields).forEach(fieldName => {
if (!this.validateField(fieldName)) {
isValid = false;
}
});
if (isValid) {
const formData = new FormData(this.form);
const data = Object.fromEntries(formData);
this.config.onSuccess(data);
} else {
this.config.onError?.(Array.from(this.errors));
}
}
getErrorElement(field) {
let errorElement = field.parentElement.querySelector('.error-message');
if (!errorElement) {
errorElement = document.createElement('div');
errorElement.className = 'error-message';
field.parentElement.appendChild(errorElement);
}
return errorElement;
}
clearFieldError(fieldName) {
const field = this.form.querySelector(`[name="${fieldName}"]`);
const errorElement = field.parentElement.querySelector('.error-message');
if (errorElement) {
errorElement.textContent = '';
errorElement.classList.remove('active');
}
field.classList.remove('error', 'success');
}
showError(field, errorElement, message) {
errorElement.textContent = message;
errorElement.classList.add('active');
field.classList.add('error');
field.classList.remove('success');
}
showSuccess(field, errorElement) {
errorElement.textContent = '';
errorElement.classList.remove('active');
field.classList.remove('error');
field.classList.add('success');
}
}
// Конфигурация валидации
const registrationConfig = {
fields: {
email: [
{ type: 'required', message: 'Email обязателен' },
{ type: 'pattern', value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: 'Неверный формат email' }
],
password: [
{ type: 'required', message: 'Пароль обязателен' },
{ type: 'minLength', value: 8, message: 'Минимум 8 символов' },
{
type: 'custom',
message: 'Пароль должен содержать цифры и буквы',
validate: (value) => /\d/.test(value) && /[a-zA-Z]/.test(value)
}
]
},
onSuccess: (data) => {
console.log('Форма валидна, данные:', data);
// Отправка на сервер
},
onError: (errors) => {
console.log('Ошибки в полях:', errors);
}
};
// Использование
new FormValidator('registration-form', registrationConfig);
Другие распространенные задачи:
- Роутинг в SPA: Реализация клиентского роутинга с History API
- Веб-компоненты: Создание переиспользуемых компонентов с Custom Elements
- Графики и визуализация: Работа с Canvas, SVG и библиотеками типа D3.js
- PWA-функционал: Service Workers, кеширование, офлайн-работа
- Интернационализация: Поддержка multiple языков и форматов
- Тестирование: Написание unit- и e2e-тестов (Jest, Cypress)
- Бандлинг и оптимизация: Настройка Webpack/Vite, code splitting, tree shaking
Каждая задача требует не только знания синтаксиса JavaScript, но и понимания архитектурных паттернов (MVC, Flux, Observer), принципов чистого кода и оптимизации производительности. Современный Frontend Developer должен уметь выбирать правильные подходы в зависимости от масштаба проекта и требований к производительности.