Почему JavaScript ломает мозг, но не должен ломать карьеру
JavaScript — это одновременно и самый дружелюбный, и самый коварный язык программирования. С одной стороны, вы пишете console.log('Hello') — и в браузере тут же появляется результат. С другой — этот же код может внезапно выдать undefined, NaN или что-то похуже, и вы будете час искать ошибку, которая прячется в одной строчке.
На pythonlib.ru мы знаем, как важно учиться на чужих граблях. В этой статье разберём 5 типичных ошибок новичков в JavaScript, которые превращают код в тыкву. И главное — покажем, как их исправить. Поехали!
Ошибка №1: Волшебное «var» и непонимание области видимости
Многие начинающие разработчики, которые изучают JavaScript, используют var для объявления переменных. Это наследие старого стандарта ES5, которое до сих пор живёт в учебниках десятилетней давности. Но var — это как старая машина без подушек безопасности: ехать можно, но при первой же аварии (читай: баге) вы сильно пострадаете.
В чём проблема?
var имеет функциональную область видимости, а не блочную. Это значит, что переменная, объявленная внутри if или for, будет доступна за их пределами.
// Пример: Ошибка с var
function testVar() {
if (true) {
var x = 10;
}
console.log(x); // 10 — работает, хотя x объявлен внутри if
}
testVar();
Теперь представьте, что у вас в проекте 1000 строк кода. Вы объявили var i в цикле, а позже случайно используете ту же переменную — получаете баг, который невозможно отследить.
Как правильно?
Используйте let и const. Они имеют блочную область видимости и ведут себя предсказуемо.
// Правильно: let и const
function testLet() {
if (true) {
let y = 20;
const z = 30;
}
console.log(y); // ReferenceError: y is not defined
}
testLet();
Совет: всегда используйте const по умолчанию. Только если переменная будет переприсваиваться — берите let. var оставьте в прошлом, как дискеты.
Ошибка №2: Забытый ключ «this» — контекст, который теряется
Ключевое слово this в JavaScript — это как сюрприз в шоколадном яйце: никогда не знаешь, что выпадет. Новички часто думают, что this всегда указывает на текущий объект. Но это не так. this зависит от того, как вызвана функция, а не где она объявлена.
Классический пример: потеря контекста в колбэке
const user = {
name: 'Анна',
greet: function() {
console.log('Привет, ' + this.name);
}
};
user.greet(); // Привет, Анна — работает
setTimeout(user.greet, 1000); // Привет, undefined — контекст потерян!
Почему так? Потому что setTimeout вызывает функцию как обычную, а не как метод объекта. this в этом случае указывает на глобальный объект (в браузере — window), у которого нет name.
Как исправить?
Три способа:
- Стрелочная функция — она не создаёт свой
this, а берёт его из внешнего контекста. - Метод
.bind()— привязывает контекст навсегда. - Хранение ссылки на
this(старый способ, лучше не использовать).
// Исправление: стрелочная функция
const user = {
name: 'Анна',
greet: function() {
console.log('Привет, ' + this.name);
}
};
setTimeout(() => user.greet(), 1000); // Привет, Анна
// Или с bind
setTimeout(user.greet.bind(user), 1000); // Привет, Анна
Ошибка №3: Асинхронность — «Почему мой fetch возвращает Promise?»
JavaScript — однопоточный язык, но он умеет работать асинхронно через колбэки, промисы и async/await. Новички часто совершают одну и ту же ошибку: пытаются использовать результат асинхронной операции как синхронный.
Пример: запрос к API
// Ошибка: пытаемся получить данные до их загрузки
let data = fetch('https://api.example.com/users');
console.log(data); // Promise {<pending>} — не то, что вы ждали
fetch возвращает Promise, а не сами данные. Вы не можете просто присвоить результат переменной и использовать его сразу.
Как правильно?
Используйте async/await — это самый читаемый способ работы с асинхронностью.
// Правильно: async/await
async function getUsers() {
try {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
console.log(data); // Теперь это реальные данные
} catch (error) {
console.error('Ошибка загрузки:', error);
}
}
getUsers();
Ещё одна частая ошибка — забыть обработать ошибки через try/catch. Без этого ваш скрипт может упасть с непонятной ошибкой, и вы будете гадать, что пошло не так.
Ошибка №4: Сравнение с «==» вместо «===»
Казалось бы, мелочь. Но эта мелочь — одна из самых частых ошибок в JavaScript, которая приводит к трудноуловимым багам. Оператор == (нестрогое равенство) выполняет приведение типов, что может дать неожиданные результаты.
Посмотрите на этот ужас:
console.log(5 == '5'); // true — строка стала числом
console.log(0 == false); // true — false превратился в 0
console.log(null == undefined); // true — они считаются равными
console.log([] == false); // true — пустой массив стал false
Если вы используете == в условиях, то легко получить логическую ошибку, которая сломает всю бизнес-логику. Например, проверка на пустую строку может внезапно пропустить 0.
Золотое правило:
Всегда используйте === (строгое равенство). Оно сравнивает и значение, и тип, не делая никаких магических преобразований.
console.log(5