Ошибки и JSON
Зачем это нужно
Программы ломаются: пользователь ввёл буквы вместо числа, сервер прислал испорченные данные, файла
нет. Без обработки одна такая ошибка останавливает всю программу. Конструкция try … catch позволяет
поймать ошибку и решить, что делать: показать сообщение, взять значение по умолчанию, попробовать снова.
А JSON — главный формат обмена данными в вебе: в нём приходят ответы сервера, хранятся настройки. Разбор «чужого» JSON — самое частое место, где нужна обработка ошибок, поэтому эти темы вместе.
Что такое ошибка
console.log("начало");
const user = null;
console.log(user.name); // TypeError — программа здесь остановится
console.log("конец"); // не выполнится
Вывод:
начало
TypeError: Cannot read properties of null (reading 'name')
Самые частые виды ошибок:
| Ошибка | Когда |
|---|---|
SyntaxError |
код записан не по правилам (или испорчен JSON) |
ReferenceError |
обращение к несуществующей переменной |
TypeError |
действие не подходит к типу: вызов не-функции, .name у null |
RangeError |
значение вне допустимого диапазона |
try … catch
try {
console.log("пробуем");
const user = null;
console.log(user.name);
console.log("сюда не дойдём");
} catch (error) {
console.log("Поймали:", error.name, "-", error.message);
}
console.log("программа работает дальше");
Вывод:
пробуем
Поймали: TypeError - Cannot read properties of null (reading 'name')
программа работает дальше
Код в try выполняется как обычно. Если в нём случилась ошибка, выполнение сразу перепрыгивает
в catch, а в переменную error попадает объект ошибки. У него есть name (вид) и message (текст).
Если ошибки не было, catch пропускается.
Если объект ошибки не нужен, скобки можно не писать: catch { … }.
finally
Блок finally выполняется всегда — была ошибка или нет. Туда кладут «уборку»: закрыть файл,
спрятать индикатор загрузки.
try {
console.log("загружаем...");
} catch (e) {
console.log("ошибка");
} finally {
console.log("прячем спиннер");
}
Вывод:
загружаем...
прячем спиннер
throw — выбросить свою ошибку
Свои функции тоже могут сообщать о проблеме, «выбрасывая» ошибку:
function buy(price, money) {
if (price > money) {
throw new Error("Недостаточно денег");
}
return money - price;
}
try {
console.log(buy(50, 100));
console.log(buy(500, 100));
} catch (e) {
console.log("Ошибка:", e.message);
}
Вывод:
50
Ошибка: Недостаточно денег
throw прерывает функцию, как return, но вместо результата «летит» ошибка — до ближайшего catch
выше по цепочке вызовов. Выбрасывать можно и конкретный вид: new TypeError(…), new RangeError(…).
Ловить только свои ошибки
Иногда нужно обработать один вид ошибки, а остальные пропустить дальше:
try {
doSomething();
} catch (e) {
if (e instanceof RangeError) {
console.log("исправим");
} else {
throw e; // не наша — пробрасываем
}
}
Ловить «всё подряд» и молча игнорировать — плохая привычка: настоящие баги будут прятаться.
JSON
JSON (JavaScript Object Notation) — текстовый формат, похожий на объекты JS:
{
"name": "Аня",
"age": 15,
"skills": ["html", "css"],
"admin": false,
"pet": null
}
Правила строже, чем у объектов JS: ключи и строки — только в двойных кавычках, нет запятой после
последнего элемента, нет комментариев, нет функций и undefined.
Объект → строка JSON: JSON.stringify
const user = { name: "Аня", age: 15, hobbies: ["рисование"] };
const text = JSON.stringify(user);
console.log(text);
console.log(typeof text);
Вывод:
{"name":"Аня","age":15,"hobbies":["рисование"]}
string
JSON.stringify(obj, null, 2) — красивый вывод с отступами в 2 пробела.
Строка JSON → объект: JSON.parse
const data = JSON.parse('{"title": "Курс JS", "lessons": 16}');
console.log(data.lessons + 1);
Вывод:
17
Если строка — не правильный JSON, JSON.parse выбрасывает SyntaxError:
try {
JSON.parse("{name: 'Аня'}"); // ключ без кавычек, одинарные кавычки
} catch (e) {
console.log(e.name);
}
Вывод:
SyntaxError
Пара JSON.parse(JSON.stringify(obj)) — старый способ сделать глубокую копию простого объекта.
Как это работает внутри
Когда выбрасывается ошибка, движок «разматывает» стек вызовов: выходит из текущей функции, потом
из той, что её вызвала, и так далее, пока не найдёт try с catch. Если не найдёт — программа
останавливается, и ошибка печатается в консоль. Поэтому catch можно поставить не прямо вокруг
опасной строки, а там, где ты знаешь, что делать с ошибкой.
У объекта ошибки есть ещё свойство stack — список функций, через которые «пролетела» ошибка.
Он очень помогает найти место поломки.
Частые ошибки
throw "текст"вместоthrow new Error("текст"). Строка не имеетname,messageиstack. Всегда выбрасывай объект ошибки.- Пустой
catch.catch {}молча проглатывает любые проблемы — баги станет невозможно найти. tryвокруг асинхронного кода. Ошибку внутри колбэкаsetTimeoutтакойtryне поймает.- Одинарные кавычки в JSON.
JSON.parse("{'a': 1}")→SyntaxError. В JSON только двойные. - Забыли, что
stringifyвозвращает строку.JSON.stringify(obj).name—undefined.
Шпаргалка
| Что | Как |
|---|---|
| Поймать ошибку | try { … } catch (e) { … } |
| Всегда выполнить | finally { … } |
| Выбросить | throw new Error("текст") |
| Конкретный вид | new TypeError(…), new RangeError(…) |
| Проверить вид | e instanceof RangeError |
| Текст и вид | e.message, e.name |
| Пробросить дальше | throw e; |
| В JSON-строку | JSON.stringify(obj) |
| Из JSON-строки | JSON.parse(text) |