Пошук уроків, статей та іншого контенту
Розглянете типи помилок у JavaScript, їхні причини та відмінність між синтаксичними, виконуваними й логічними помилками.
Помилка в JavaScript — це ситуація, через яку програма:
не може запуститися;
припиняє виконання під час роботи;
працює, але повертає неправильний результат.
Помилки трапляються навіть у невеликих програмах. Важливо вміти визначити їхній тип, знайти причину та виправити її.
Основні типи помилок:
синтаксичні — код порушує правила мови;
помилки виконання — проблема виникає під час виконання програми;
логічні — програма виконується, але результат неправильний.
Синтаксис — це правила запису коду. Якщо JavaScript не може правильно розібрати програму, виникає синтаксична помилка (SyntaxError).
Наприклад, у цьому коді пропущена закривальна дужка:
console.log("Привіт";Браузер або Node.js повідомить про помилку на кшталт:
SyntaxError: missing ) after argument listЧерез синтаксичну помилку програма не почне виконуватися.
пропущена дужка або лапка;
неправильне використання ключового слова;
пропущена кома між властивостями об’єкта;
неправильне оформлення умови або циклу;
використання конструкції, якої не існує в JavaScript.
Приклад неправильного об’єкта:
const user = {
name: "Олена"
age: 25
};Між властивостями name і age пропущена кома.
Правильний варіант:
const user = {
name: "Олена",
age: 25
};Повідомлення про помилку зазвичай містить:
тип помилки;
опис проблеми;
файл і номер рядка, де її виявлено.
Наприклад, під час виправлення варто:
перейти до вказаного рядка;
перевірити дужки, лапки та коми;
переглянути кілька рядків перед ним;
звернути увагу на місце, де починається конструкція.
Помилка може бути вказана не точно в місці пропуску. Наприклад, якщо не закрити дужку раніше, JavaScript може повідомити про проблему в наступному рядку.
Помилка виконання виникає вже після успішного розбору коду. Програма починає працювати, але під час виконання зустрічає ситуацію, з якою не може впоратися.
Наприклад:
const user = null;
console.log(user.name);Синтаксис правильний, але значення user дорівнює null. У нього немає властивості name, тому виникне TypeError.
ReferenceErrorReferenceError виникає, коли програма звертається до змінної, якої не існує або яка недоступна в поточній області видимості.
console.log(username);Змінна username не була оголошена, тому JavaScript повідомить:
ReferenceError: username is not definedПравильний варіант:
const username = "Ірина";
console.log(username);TypeErrorTypeError виникає, коли операція застосовується до значення неправильного типу.
const age = 25;
age.toUpperCase();Метод toUpperCase() призначений для рядків, а age є числом.
Інший приклад:
const numbers = null;
numbers.push(10);Метод push() можна викликати в масиву, але не в null.
RangeErrorRangeError виникає, коли значення виходить за допустимий діапазон.
Наприклад:
const numbers = new Array(-1);Масив не може мати від’ємну кількість елементів, тому виникне RangeError.
Ще один приклад:
const number = 10;
number.toFixed(110);Кількість цифр після десяткової крапки для toFixed() не може бути такою великою.
URIErrorURIError виникає під час неправильного використання функцій для роботи з URI, наприклад decodeURIComponent().
decodeURIComponent("%");Рядок % не є правильно закодованою частиною URI.
try...catchЯкщо помилка виконання виникла в блоці try, її можна перехопити в блоці catch.
try {
const data = JSON.parse('{"name":"Олена"}');
console.log(data.name);
} catch (error) {
console.log("Не вдалося обробити дані.");
}У цьому прикладі JSON правильний, тому помилки не виникне.
Якщо передати неправильний JSON:
try {
const data = JSON.parse("{name: Олена}");
console.log(data);
} catch (error) {
console.log("Рядок не є правильним JSON.");
}Функція JSON.parse() створить помилку, але програма не завершиться аварійно: керування перейде до catch.
Змінна error у catch містить інформацію про помилку.
try {
const result = JSON.parse("неправильний JSON");
console.log(result);
} catch (error) {
console.log(error.name);
console.log(error.message);
}Властивості:
error.name — назва типу помилки;
error.message — опис помилки;
error.stack — стек викликів, корисний для пошуку місця виникнення помилки.
Не варто показувати користувачам технічний stack. Він призначений переважно для розробника.
finallyБлок finally виконується незалежно від того, виникла помилка чи ні.
try {
console.log("Спроба виконати операцію");
} catch (error) {
console.log("Сталася помилка");
} finally {
console.log("Операцію завершено");
}finally часто використовують для дій, які потрібно виконати в будь-якому випадку: очищення даних, закриття ресурсу або приховування індикатора завантаження.
function parseUser(json) {
try {
const user = JSON.parse(json);
if (typeof user.name !== "string") {
throw new Error("Ім'я користувача має бути рядком");
}
return user;
} catch (error) {
console.log(`Помилка: ${error.message}`);
return null;
} finally {
console.log("Обробку завершено");
}
}
const user = parseUser('{"name":"Марія"}');
if (user !== null) {
console.log(`Користувач: ${user.name}`);
}У цьому прикладі:
JSON.parse() перетворює рядок на об’єкт;
перевіряється тип властивості name;
throw new Error() створює помилку вручну;
catch обробляє помилку;
finally виконується в будь-якому випадку.
Для створення помилки використовують throw.
function divide(a, b) {
if (b === 0) {
throw new Error("Ділити на нуль не можна");
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (error) {
console.log(error.message);
}throw можна використовувати з об’єктами помилок:
new Error();
new TypeError();
new RangeError();
іншими вбудованими типами помилок.
Тип помилки варто обирати відповідно до ситуації. Наприклад, TypeError доречний, якщо функція отримала значення неправильного типу.
function getFirstElement(value) {
if (!Array.isArray(value)) {
throw new TypeError("Очікувався масив");
}
return value[0];
}
try {
console.log(getFirstElement("текст"));
} catch (error) {
console.log(`${error.name}: ${error.message}`);
}Логічна помилка не заважає програмі виконуватися. JavaScript не показує помилку, тому що код написаний синтаксично правильно.
Проблема полягає в неправильному алгоритмі або припущенні розробника.
function isAdult(age) {
return age > 18;
}
console.log(isAdult(18));Програма виконається, але для більшості правил повноліття правильна перевірка має включати 18:
function isAdult(age) {
return age >= 18;
}
console.log(isAdult(18));function calculateTotal(price, quantity) {
return price + quantity;
}
console.log(calculateTotal(100, 3));Якщо потрібно обчислити загальну вартість, слід множити ціну на кількість:
function calculateTotal(price, quantity) {
return price * quantity;
}
console.log(calculateTotal(100, 3)); // 300У першій версії немає синтаксичної або виконуваної помилки. Але результат 103 неправильний з погляду вимог задачі.
Допомагають такі прийоми:
перевірка проміжних значень через console.log();
тестування граничних випадків;
порівняння результату з очікуваним;
розбиття великої функції на менші;
використання налагоджувача та точок зупинки;
написання автоматизованих тестів.
Наприклад, для функції isAdult() варто перевірити значення:
17;
18;
19;
0;
від’ємне число.
const message = "Привіт;виникає під час розбору коду;
програма не запускається;
зазвичай має тип SyntaxError.
const user = null;
console.log(user.name);код починає виконуватися;
помилка виникає під час конкретної операції;
часто має тип ReferenceError, TypeError або інший вбудований тип.
const result = 2 + 2;
console.log(result === 5);програма виконується;
JavaScript не вважає код помилковим;
результат не відповідає задуму розробника.
Коли програма працює неправильно, дійте послідовно:
Прочитайте повідомлення про помилку.
Зверніть увагу на її тип і номер рядка.
Знайдіть першу помилку.
Наступні повідомлення можуть бути її наслідками.
Перевірте значення змінних.
Виведіть їх за допомогою console.log() або перегляньте в налагоджувачі.
Перевірте типи.
const value = "25";
console.log(typeof value);Перевірте граничні випадки.
Наприклад, порожній рядок, 0, null, undefined або порожній масив.
Зменште проблему.
Тимчасово приберіть зайвий код і залиште мінімальний приклад, у якому помилка відтворюється.
Перевірте виправлення.
Після зміни коду протестуйте не лише проблемний випадок, а й інші сценарії.
= та ===Оператор = присвоює значення, а === порівнює значення і тип.
const age = 18;
if (age === 18) {
console.log("Вік дорівнює 18");
}Використання = в умові може призвести до логічної помилки або до несподіваної поведінки.
null і undefinedПеред зверненням до властивості перевіряйте, чи існує об’єкт:
const user = null;
if (user !== null) {
console.log(user.name);
}У сучасному JavaScript для безпечного доступу також можна використовувати оператор ?.:
const user = null;
console.log(user?.name);У цьому випадку результатом буде undefined, а помилка не виникне.
catchНевдалий приклад:
try {
doSomething();
} catch (error) {
}Такий код приховує проблему, і знайти її стає складніше.
Краще хоча б записати інформацію про помилку:
try {
doSomething();
} catch (error) {
console.error("Не вдалося виконати операцію:", error);
}try...catch замість перевірки логікиtry...catch призначений для обробки помилок, які можуть виникнути під час виконання. Він не виправляє неправильний алгоритм.
Якщо функція повертає неправильне значення, потрібно перевірити її умови та обчислення, а не просто помістити виклик у try...catch.
Синтаксичні помилки порушують правила запису коду та не дають програмі запуститися.
Помилки виконання виникають під час роботи програми, наприклад під час доступу до властивості null.
Логічні помилки не зупиняють програму, але призводять до неправильного результату.
SyntaxError, ReferenceError, TypeError і RangeError — поширені вбудовані типи помилок.
try...catch дає змогу перехоплювати та обробляти помилки виконання.
throw використовується для створення помилок вручну.
Для пошуку логічних помилок потрібно перевіряти проміжні значення, граничні випадки та очікуваний результат.
Не слід приховувати помилки порожнім блоком catch.