Антипаттерны: чего избегать
Антипаттерн — повторяющийся подход к решению задачи, который выглядит разумным, но на практике приводит к проблемам: трудноуловимым багам, низкой производительности, плохой поддерживаемости.
Зачем нужно
Знание антипаттернов позволяет распознавать опасные практики в своём и чужом коде до того, как они превратятся в баги или технический долг. Это важная часть code review и написания качественного JavaScript.
Где используется
Знание антипаттернов применяется при любом написании JS: в функциях, работе с DOM, асинхронном коде, ООП.
Антипаттерны в JavaScript
1. Загрязнение глобального пространства имён
// Плохо
var user = { name: 'Иван' }; // глобальная переменная
function loadData() { ... } // глобальная функция
// Хорошо — оборачивать в модуль или IIFE
const App = (function {
const user = { name: 'Иван' };
function loadData() { ... }
return { loadData };
});
2. Расширение встроенных прототипов
// Плохо: может сломать сторонние библиотеки
Array.prototype.last = function { return this[this.length - 1]; };
// Хорошо: вспомогательная функция
function last(arr) { return arr[arr.length - 1]; }
3. eval
// Плохо: медленно, опасно, трудно отлаживать
const code = 'console.log("Привет")';
eval(code);
// Хорошо: явный вызов функции
function doSomething() { console.log('Привет'); }
doSomething;
4. Callback Hell
// Плохо: «пирамида смерти»
getData(function(a) {
getMoreData(a, function(b) {
getEvenMoreData(b, function(c) {
console.log(c);
});
});
});
// Хорошо: async/await
async function main() {
const a = await getData;
const b = await getMoreData(a);
const c = await getEvenMoreData(b);
console.log(c);
}
5. Прямая мутация аргументов функции
// Плохо: мутирует переданный объект неожиданно
function addDiscount(order) {
order.price *= 0.9; // изменяет оригинал!
return order;
}
// Хорошо: возвращаем новый объект
function addDiscount(order) {
return { ...order, price: order.price * 0.9 };
}
6. Магические числа и строки
// Плохо
if (status === 3) { ... }
// Хорошо
const STATUS = { PENDING: 1, ACTIVE: 2, CLOSED: 3 };
if (status === STATUS.CLOSED) { ... }
7. Слишком длинные функции
// Плохо: функция делает всё сразу (200 строк)
function processOrder(order) {
// валидация, расчёт стоимости, применение скидок,
// сохранение в БД, отправка уведомления — всё в одном
}
// Хорошо: разбить на маленькие функции с одной ответственностью
function validateOrder(order) { ... }
function calculateTotal(order) { ... }
function applyDiscounts(order) { ... }
Частые ошибки
- Использование
==вместо===— нестрогое равенство делает неявные преобразования типов (0 == ''→true); всегда используйте===. - Синхронные операции в асинхронном контексте — тяжёлые вычисления в обработчиках событий блокируют поток.
- Игнорирование результатов промисов — незакрытые
Promiseбез.catchсоздают необработанные ошибки.
Связанные темы
- _MOC Паттерны
- _MOC JavaScript
- _MOC Асинхронность
- Иммутабельность и функции
- Глобальная и локальная область видимости