Типы ошибок
Последнее обновление: 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, а не в браузере.// возводим число Х в степень У и отправляем в переменную resultresult = math.pow(x,y);Что делать с ошибкой ReferenceError
// возводим число Х в степень У и отправляем в переменную resultresult = 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;
}
