Типы ошибок
Последнее обновление: 30.08.2021
В блоке мы можем получить информацию об ошибке, которая представляет объект. Все ошибки, которые генерируются интерретатором JavaScript,
предоставляют объект типа , который имеет ряд свойств:
-
: сообщение об ошибке
-
: тип ошибки
Стоит отметить, что отдельные браузеры поддерживают еще ряд свойств, но их поведение в зависимости от браузера может отличаться:
-
: название файла с кодом JavaScript, где произошла ошибка
-
: строка в файле, где произошла ошибка
-
: столбец в строке, где произошла ошибка
-
: стек ошибки
Получим данные ошибки, например, при вызове несуществующей функции:
try{ callSomeFunc(); } catch(error){ console.log("Тип ошибки:", error.name); console.log("Ошибка:", error.message); }
Тип ошибки: ReferenceError Ошибка: callSomeFunc is not defined
Типы ошибок
Выше мы рассмотрели, что генерируемая интерпретатором ошибка представляет тип Error, однако при вызове несуществующей функции
генерируется ошибка типа . Дело в том, что тип Error представляет общий тип ошибок. В то же время есть конкретные типы ошибок для определенных ситуаций:
-
: представляет ошибку, которая генерируется при выполнении глобальной функции
eval()
-
: ошибка генерируется, если параметр или переменная, представляют число, которое находится вне некотоого допустимого диапазона
-
: ошибка генерируется при обращении к несуществующей ссылке
-
: представляет ошибку синтаксиса
-
: ошибка генерируется, если значение переменной или параметра представляют некорректный тип или пр попытке изменить значение, которое нельзя изменять
-
: ошибка генерируется при передаче функциям
encodeURI()
иdecodeURI()
некорректных значений -
: предоставляет ошибку, которая объединяет несколько возникших ошибок
Например, при попытке присвоить константе второй раз значение, генерируется ошибка TypeError
:
try{ const num = 9; num = 7; } catch(error){ console.log(error.name); // TypeError console.log(error.message); // Assignment to constant variable. }
Применение типов ошибок
При генерации ошибок мы можем использовать встроенные типы ошибок. Например:
class Person{ constructor(name, age){ if(age < 0) throw new Error("Возраст должен быть положительным"); this.name = name; this.age = age; } print(){ console.log(`Name: ${this.name} Age: ${this.age}`);} } try{ const tom = new Person("Tom", -45); tom.print(); } catch(error){ console.log(error.message); // Возраст должен быть положительным }
Здесь конструктор класса Person принимает значения для имени и возаста человека. Если передан отрицательный возраст, то генерируем ошибку в виде объекта Error. В качестве параметра в
конструктор Error передается сообщение об ошибке:
if(age < 0) throw new Error("Возраст должен быть положительным");
В итоге при обработке исключения в блоке catch мы сможем получить переданное сообщение об ошибке.
Все остальные типы ошибок в качестве первого параметра в конструкторе также принимают сообщение об ошибке. Так, сгенерируем несколько типов ошибок:
class Person{ constructor(pName, pAge){ const age = parseInt(pAge); if(isNaN(age)) throw new TypeError("Возраст должен представлять число"); if(age < 0 || age > 120) throw new RangeError("Возраст должен быть больше 0 и меньше 120"); this.name = pName; this.age = age; } print(){ console.log(`Name: ${this.name} Age: ${this.age}`);} }
Поскольку для возраста можно ередатьне только число, но и вообще какое угодно значение, то вначале мы пытаемся преобразовать это значение в число с помощью
функции parseInt()
:
const age = parseInt(pAge); if(isNaN(age)) throw new TypeError("Возраст должен представлять число");
Далее с помощью функции isNaN(age)
проверяем, является полученное число числом. Если age – НЕ число, то данная функция возвращает true
. Поэтому
генерируется ошибка типа TypeError
.
Затем проверяем, что полученное число входит в допустимый диапазон. Если же не входит, генерируем ошибку типа RangeError
:
if(age < 0 || age > 120) throw new RangeError("Возраст должен быть больше 0 и меньше 120");
Проверим генерацию исключений:
try{ const tom = new Person("Tom", -45); } catch(error){ console.log(error.message); // Возраст должен быть больше 0 и меньше 120 } try{ const bob = new Person("Bob", "bla bla"); } catch(error){ console.log(error.message); // Возраст должен представлять число } try{ const sam = new Person("Sam", 23); sam.print(); // Name: Sam Age: 23 } catch(error){ console.log(error.message); }
Возраст должен быть больше 0 и меньше 120 Возраст должен представлять число Name: Sam Age: 23
Обработка нескольких типов ошибок
При выполнении одного и то же кода могут генерироваться ошибки разных типов. И иногда бывает необходимо разграничить обработку разных типов.
В этом случае мы можем проверять тип возникшей ошибки. Например, пример выше с классом Person:
class Person{ constructor(pName, pAge){ const age = parseInt(pAge); if(isNaN(age)) throw new TypeError("Возраст должен представлять число"); if(age < 0 || age > 120) throw new RangeError("Возраст должен быть больше 0 и меньше 120"); this.name = pName; this.age = age; } print(){ console.log(`Name: ${this.name} Age: ${this.age}`);} } try{ const tom = new Person("Tom", -45); const bob = new Person("Bob", "bla bla"); } catch(error){ if (error instanceof TypeError) { console.log("Некорректный тип данных."); } else if (error instanceof RangeError) { console.log("Недопустимое значение"); } console.log(error.message); }
Создание своих типов ошибок
Мы не ограничены встроенными только встроенными типами ошибок и при необходимости можем создавать свои типы ошибок, предназначеные для каких-то конкретных ситуаций.
Например:
class PersonError extends Error { constructor(value, ...params) { // остальные параметры передаем в конструктор базового класса super(...params) this.name = "PersonError" this.argument = value; } } class Person{ constructor(pName, pAge){ const age = parseInt(pAge); if(isNaN(age)) throw new PersonError(pAge, "Возраст должен представлять число"); if(age < 0 || age > 120) throw new PersonError(pAge, "Возраст должен быть больше 0 и меньше 120"); this.name = pName; this.age = age; } print(){ console.log(`Name: ${this.name} Age: ${this.age}`);} } try{ //const tom = new Person("Tom", -45); const bob = new Person("Bob", "bla bla"); } catch(error){ if (error instanceof PersonError) { console.log("Ошибка типа Person. Некорректное значение:", error.argument); } console.log(error.message); }
Ошибка типа Person. Некорректное значение: bla bla Возраст должен представлять число
Для представления ошибки класса Person здесь определен тип PersonError
, который наследуется от класса Error:
class PersonError extends Error { constructor(value, ...params) { // остальные параметры передаем в конструктор базового класса super(...params) this.name = "PersonError" this.argument = value; } }
В конструкторе мы определяем дополнительное свойство – argument
. Оно будет хранить значение, которое вызвало ошибку. С помощью параметра value
конструктора
получаем это значение. Кроме того, переопреляем имя типа с помощью свойства this.name
.
В классе Person используем этот тип, передавая в конструктор PersonError соответствующие значения:
if(isNaN(age)) throw new PersonError(pAge, "Возраст должен представлять число"); if(age < 0 || age > 120) throw new PersonError(pAge, "Возраст должен быть больше 0 и меньше 120");
Затем при обработки исключения мы можем проверить тип, и если он представляет класс PersonError, то обратиться к его свойству argument
:
catch(error){ if (error instanceof PersonError) { console.log("Ошибка типа Person. Некорректное значение:", error.argument); } console.log(error.message); }
new () new (message) new (message, options) new (message, fileName) new (message, fileName, lineNumber) () (message) (message, options) (message, fileName) (message, fileName, lineNumber)
new
, так и без него . Оба создают новый экземпляр ReferenceError
.
-
Человеческое описание ошибки.
-
Объект,обладающий следующими свойствами:
-
Свойство,указывающее на конкретную причину ошибки.При перехвате и повторном отбрасывании ошибки с более конкретным или полезным сообщением об ошибке это свойство можно использовать для передачи исходной ошибки.
-
Имя файла,содержащего код,который вызвал исключение.
-
Номер строки кода,вызвавшего исключение
Поймать ошибку в ссылке
{ a = undefinedVariable } (e) { .(e ) .(e.) .(e.) .(e.) .(e.) .(e.) .(e.) }
Создание ссылочной ошибки
{ (, , ) } (e) { .(e ) .(e.) .(e.) .(e.) .(e.) .(e.) .(e.) }
Browser compatibility
JavaScript
Поймать ошибку в ссылке
{ a = undefinedVariable } (e) { .(e ) .(e.) .(e.) .(e.) .(e.) .(e.) .(e.) }
Создание ссылочной ошибки
{ (, , ) } (e) { .(e ) .(e.) .(e.) .(e.) .(e.) .(e.) .(e.) }
Browser compatibility
JavaScript
“x” не определено
области . функции, не могут быть доступны из любого места за пределами функции, потому что переменная определяется только в области видимости функции. Однако функция может получить доступ ко всем переменным и функциям,определенным в области видимости,в которой она определена.Другими словами,функция,определенная в глобальной области видимости,может получить доступ ко всем переменным,определенным в глобальной области видимости. Ситуация: нам нужно быстро дописать код, но не хватает одной функции. Мы не знаем, как её быстро реализовать, поэтому идём за ней в интернет — и находим: Внешне вроде всё хорошо, но при запуске компьютер выдаёт ошибку: ❌ReferenceError: Can’t find variable: x Откуда ошибка, ведь все переменные у нас есть? Что это значит: JavaScript встретил переменную, которую ему сказали использовать, но он не знает, где её брать. В нашем случае это происходит в последней строке: Возможно, автор исходного кода имел в виду, что у вас где-то ранее эти переменные определяются; или что вы будете использовать последнюю строку для отладки на тестовых данных. В любом случае он не предусмотрел, что эти переменные у вас могут быть не определены. Чтобы исправить ошибку, нужно определить переменную до того, как вы её начн`те использовать. Например: Если хотите, можно спросить значение у пользователя (коряво, но мы так иногда делаем): Можно получить значение элементов веб-страницы, можно запросить их с сервера через асинхронный запрос. Это уже зависит от того, какая у вас страница. А ещё можно просто не использовать переменные, пока они не понадобятся. По сути, в нашем коде выше не было никакой необходимости выводить сумму чисел сразу после определения функции. Можно убрать последнюю строку с console.log() и жить спокойно. Иногда такая ошибка возникает при использовании специальных библиотечных функций в браузере или без предварительного импорта. Например, команда Представьте такое: вы делаете онлайн-калькулятор на JavaScript и хотите реализовать, например, функцию возведения в степень. Вы идёте в Яндекс, вбиваете в поиск «возведение в степень javascript». По первой строке в результатах всё понятно: нам нужна функция math.pow() из стандартной математической библиотеки math. Пишем код: Этот код при запуске вываливается с ошибкой: ❌ ReferenceError: math is not defined Это означает: «Я не знаю, что такое math, поэтому не буду это выполнять». При этом вы точно уверены, что всё в порядке, потому что все остальные сайты дают именно такую же команду. Но всё проще, чем вы думаете. Дело в том, что в JavaScript все имена встроенных объектов пишутся с большой буквы. Math — тоже встроенный объект, поэтому его тоже нужно писать с большой буквы. Чтобы исправить нашу ошибку, этого будет достаточно: Теперь ошибки нет, и мы можем продолжать делать свой онлайн-калькулятор. JavaScript — регистрозависимый язык. Это значит, что он различает строчные и прописные буквы в названиях переменных, командах и функциях. Например, hello, Hello и HELLO — три разные переменные с точки зрения JavaScript. По этой причине нужно перепроверять все команды, которые вы находите на любых сайтах — возможно, там есть ошибка в синтаксисе. А иногда программист просто забывает написать нужную команду с большой буквы. Такие дела. Ситуация: вы пишете код, который обрабатывает нажатия на клавиши для управления в игре. Вы вспоминаете, что нужно сделать отдельную функцию для проверки на попадание в цель. Для этого вы хотите сравнить текущие координаты с координатами цели — если они совпадают, то есть попадание. В результате получается такой код: Но при запуске игра падает с ошибкой: ❌ ReferenceError: Invalid left-hand side in assignment Что случилось: браузер видит условный оператор if и хочет выполнить сравнения в скобках. Если равенство выполняется, то условие истинно и можно выполнить команду вывода на экран. Но вместо сравнения браузер встречает оператор присваивания, понимает, что ему тут не место, и останавливает программу. Чтобы ошибки не было, нужно использовать не один знак равенства, а два. Один — присваивание, два — сравнение: Когда встречается: когда мы делаем что-то не то с левой частью выражения — присваиваем вместо сравнения или перенаправляем вывод в переменную, которая не предназначена для такого. Ещё такая ошибка бывает, когда что-то пытаются присвоить ключевому слову this — оно хоть и похоже на переменную по поведению, но присваивать ему новое значение так нельзя. Скорее всего, вы используете присваивание вместо сравнения. Это частая ошибка у новичков, потому что в математике знак «=» означает именно равенство. Если дело не в этом, то вот вопросы, которые помогут вам с поиском ошибки: Задание со звёздочкой: есть такой фрагмент кода на странице И есть такой скрипт, который при нажатии на кнопку падает с нашей ошибкой: defined (V8-based & Firefox)
Can
Что пошло не так?
<script>
, загружающий библиотеку, перед кодом, который его использует.Переменная не объявлена
String.prototype.substring()
работал. foo = ;
foo.substring();
() {
num1 = ;
num2 = ;
num1 + num2;
}
.(num1);
num1 = ;
num2 = ;
() {
num1 + num2;
}
.(());
JavaScript
// складываем два числа, которые на самом деле — строки; возвращаем строку
function plus(a,b) {
// тут будет результат
var result = '';
// переводим строки в числа
x = parseInt(a);
y = parseInt(b);
// получаем результат
result += x + y;
// и возвращаем ответ в виде строки
return(String(result));
}
console.log(plus(x,y));
console.log(plus(x,y));
— мы сказали «выведи в консоль результат сложения X и Y», но не сказали, что это за икс и игрек. Что делать с ошибкой ReferenceError
let x = '11';
let y = '12';
console.log(plus(x,y)); let x = prompt("Введите первое число");
let y = prompt("Введите второе число");
console.log(plus(x,y));Где ещё
const axios = require("axios");
при запуске в браузере тоже выдаст ошибку, потому что эта команда предполагает запуск в среде Node.js, а не в браузере.// возводим число Х в степень У и отправляем в переменную result
result = math.pow(x,y);
Что делать с ошибкой ReferenceError
// возводим число Х в степень У и отправляем в переменную result
result = Math.pow(x,y);
Объясните подробнее
Invalid left-hand side in assignment
Попробуйте сами
if (Math.PI = 3 || Math.PI = 4) {
console.log('Потрачено!');
}
var str = 'Привет, '
+= 'это журнал '
+= 'Код!';
<input type=»text» id=»number»><br>
Enter exponent:<br>
<input type=»text» id=»degree»><br><br><br>
<button id=»button»>Result</button>
<input type=»text» id=»result»>
var button = document.getElementById('button');
button.addEventListener('click', math);
function math(a,b){
var a = document.getElementById('number').value;
var b = document.getElementById('degree').value;
var result = Math.pow(a,b);
document.getElementById('result') = result;
}