Изучаем JavaScript на примерах: от циклов до обработки ошибок
Основные примеры кода на JavaScript
В этом разделе рассматриваются часто встречающиеся задачи при написании кода на JavaScript. Для каждой задачи приведено основное эффективное решение, а также альтернативные варианты с указанием целей и возможных проблем.
Как перебрать массив?
Цель: последовательно обработать каждый элемент массива. Основной метод – forEach.
Решение с использованием forEach:
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(function(element, index) {
console.log(`Элемент ${index}: ${element}`);
});
Find js (поиск в javascript)
Метод forEach выполняет переданную функцию для каждого элемента массива. Первый аргумент – текущий элемент, второй – индекс. Этот способ удобен для побочных эффектов, не создаёт новый массив.
Как использовать классический цикл for?
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
Js примеры (примеры кода на javascript)
Цикл for даёт полный контроль над индексом и условием остановки. Применяется, когда требуется прервать цикл (break) или пропустить итерацию (continue).
Как применить for...of для простого перебора значений?
for (const value of numbers) {
console.log(value);
}
Javascript строки (строки в javascript)
Конструкция for...of перебирает значения итерируемых объектов (массивы, строки, Map, Set). Код более лаконичен, но не предоставляет индекс напрямую.
Как создать новый массив на основе существующего с помощью map?
const doubled = numbers.map(x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
Js фильтр (фильтрация в javascript)
Метод map возвращает новый массив той же длины, где каждый элемент преобразован согласно функции. Идеален для трансформации данных без мутации исходного массива.
Возможные проблемы:
- В forEach нельзя использовать break или continue. Для досрочного выхода требуется цикл for или some/every.
- В старых браузерах forEach может отсутствовать (полифилл).
- При передаче функции с контекстом (например, метод объекта) теряется привязка this. Решение – использовать стрелочную функцию или bind.
- Цикл for с var создаёт глобальную переменную, лучше применять let.
Как объявить и вызвать функцию?
Цель: определить блок кода, который можно многократно выполнять с разными аргументами. Основной способ – function declaration.
function greet(name) {
return `Привет, ${name}!`;
}
console.log(greet('Анна')); // Привет, Анна!
Javascript переменные (переменные в javascript)
Объявление функции через function всплывает (hoisting), поэтому её можно вызвать до объявления. Подходит для всех сценариев.
Как использовать function expression?
const greetExpr = function(name) {
return `Привет, ${name}!`;
};
console.log(greetExpr('Пётр'));
Meta js (мета-теги в javascript)
Функциональное выражение присваивается переменной. Не всплывает, поэтому вызывать можно только после объявления. Удобно для анонимных функций.
Когда применяется стрелочная функция (arrow function)?
const greetArrow = (name) => `Привет, ${name}!`;
console.log(greetArrow('Мария'));
Href javascript (ссылки javascript)
Стрелочные функции не имеют собственного this и arguments. Они наследуют контекст из внешней области. Компактны, особенно для коротких операций.
Возможные проблемы:
- Стрелочные функции не подходят для методов объекта, если требуется доступ к this объекта.
- function declaration может быть переопределена, что иногда приводит к путанице.
- При использовании function expression без имени (анонимная) стек вызовов менее информативен при отладке.
Как работать со свойствами объекта?
Цель: хранить и извлекать данные в формате ключ-значение. Базовый способ – точечная нотация.
const user = { name: 'Иван', age: 30 };
console.log(user.name); // Иван
user.age = 31;
Js приложения (приложения на javascript)
Точечная нотация проста и читаема. Подходит для статически известных имён свойств.
Как использовать квадратные скобки для динамических ключей?
const key = 'name';
console.log(user[key]); // Иван
user['newKey'] = 'value';
Квадратные скобки позволяют обращаться к свойствам через строку или переменную. Обязательны, если имя свойства содержит пробелы или начинается с цифры.
Как скопировать или объединить объекты?
const clone = Object.assign({}, user);
const merged = { ...user, age: 32 };
Object.assign и оператор расширения (spread) создают поверхностную копию. Полезны для обновления состояния без мутации.
Возможные проблемы:
- Поверхностное копирование не затрагивает вложенные объекты (глубокое копирование требует дополнительных действий).
- Оператор spread не копирует методы прототипа.
- Обращение к несуществующему свойству возвращает undefined, что может привести к скрытым ошибкам.
Как обработать ошибку в JavaScript?
Цель: корректно реагировать на исключительные ситуации. Основная конструкция – try...catch.
try {
const result = JSON.parse('некорректный JSON');
} catch (error) {
console.error('Ошибка парсинга:', error.message);
}
Блок try содержит код, который может выбросить исключение. Если ошибка возникает, управление переходит в catch, где её можно обработать.
Как использовать блок finally?
try {
// код
} catch (e) {
// обработка
} finally {
console.log('Это выполняется всегда');
}
finally выполняется в любом случае (даже если в try был return). Подходит для освобождения ресурсов (закрытие файлов, очистка таймеров).
Как выбросить собственную ошибку?
function divide(a, b) {
if (b === 0) {
throw new Error('Деление на ноль');
}
return a / b;
}
С помощью throw можно создавать пользовательские ошибки, используя встроенный класс Error или его подклассы.
Возможные проблемы:
- Слишком широкий catch (без проверки типа ошибки) может скрыть программные ошибки.
- Блок finally не предотвращает распространение ошибки, если он не содержит return или другой выброс.
- При асинхронных операциях (промисы, async/await) конструкция try...catch работает только с await.
Расширенные примеры использования
Пример 1: reduce для вычисления сводной статистики
Метод reduce позволяет свернуть массив в одно значение, но его можно применять и для более сложных агрегаций.
const purchases = [
{ product: 'Книга', price: 500, quantity: 2 },
{ product: 'Тетрадь', price: 50, quantity: 10 },
{ product: 'Ручка', price: 30, quantity: 5 }
];
const totalCost = purchases.reduce((acc, item) => {
return acc + item.price * item.quantity;
}, 0);
console.log('Общая стоимость:', totalCost);
Общая стоимость: 1650
Пример 2: Замыкание для создания счётчика с приватным состоянием
Замыкания сохраняют доступ к переменным внешней функции даже после её завершения. Это основа для инкапсуляции.
function createCounter(start = 0) {
let count = start;
return {
increment() { return ++count; },
decrement() { return --count; },
reset() { count = start; return count; }
};
}
const counter = createCounter(10);
console.log(counter.increment()); // 11
console.log(counter.decrement()); // 10
console.log(counter.reset()); // 10
11 10 10
Пример 3: Proxy для валидации свойств объекта
Объект Proxy перехватывает операции над объектом. Можно, например, проверять тип присваиваемого значения.
const validator = {
set(target, property, value) {
if (property === 'age' && (typeof value !== 'number' || value < 0)) {
throw new TypeError('Возраст должен быть неотрицательным числом');
}
target[property] = value;
return true;
}
};
const person = new Proxy({}, validator);
person.name = 'Алексей';
person.age = 25;
console.log(person.age); // 25
// person.age = -5; // Выбросит TypeError
25
Пример 4: Обработка ошибок в асинхронных функциях с async/await
При работе с промисами блок try...catch корректно ловит ошибки, выброшенные внутри async функции.
async function fetchUserData(userId) {
try {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const user = await response.json();
console.log('Имя пользователя:', user.name);
} catch (error) {
console.error('Не удалось загрузить данные:', error.message);
}
}
fetchUserData(1);
Имя пользователя: Leanne Graham
В реальном приложении вместо console.log данные отображаются в интерфейсе.
Пример 5: Генератор для бесконечной последовательности
Генераторы позволяют приостанавливать и возобновлять выполнение, возвращая последовательность значений по требованию.
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
0 1 1 2 3