Error и стандартные ошибки

Какие бывают стандартные ошибки в JavaScript и как создавать собственные типы ошибок.

Время чтения: меньше 5 мин

Кратко

Скопировано

Программа может работать правильно, только если код написан корректно и не содержит ошибок. JavaScript умеет обрабатывать некорректный код и сообщать об ошибке в коде. Существует семь встроенных видов ошибок, также можно создать свои собственные. Встроенные ошибки генерируются самим движком JavaScript при выполнении программы, а пользовательские — создаются с помощью конструктора Error. Оба типа ошибок можно ловить в конструкции try...catch.

Как понять

Скопировано

Error

Скопировано

Общий конструктор ошибок.

        
          
          new Error('Общая ошибка. Проверьте код')
          new Error('Общая ошибка. Проверьте код')

        
        
          
        
      

Вызов конструктора возвращает объект ошибки со следующими свойствами:

  • message представляет человекопонятное описание ошибки для встроенных типов (SyntaxError, TypeError и так далее) и переданное в конструктор значение для общего типа Error.
  • name — имя типа (класса) ошибки.
        
          
          const commonError = new Error('Общая ошибка. Проверьте код')console.log(commonError.message)// 'Общая ошибка. Проверьте код'console.log(commonError.name)// 'Error'
          const commonError = new Error('Общая ошибка. Проверьте код')

console.log(commonError.message)
// 'Общая ошибка. Проверьте код'

console.log(commonError.name)
// 'Error'

        
        
          
        
      

Нестандартное свойство stack показывает, на какой строке кода возникла ошибка. Первая строка отформатирована как <имя класса ошибок>: <сообщение об ошибке>, и за ней следует серия кадров стека (каждая строка начинается с «at»).

Пример из документации к движку V8:

ReferenceError: FAIL is not defined
  at Constraint.execute (deltablue.js:525:2)
  at Constraint.recalculate (deltablue.js:424:21)
  at Planner.addPropagate (deltablue.js:701:6)
  at Constraint.satisfy (deltablue.js:184:15)
  at Planner.incrementalAdd (deltablue.js:591:21)
  at Constraint.addConstraint (deltablue.js:162:10)
  at Constraint.BinaryConstraint (deltablue.js:346:7)
  at Constraint.EqualityConstraint (deltablue.js:515:38)
  at chainTest (deltablue.js:807:6)
  at deltaBlue (deltablue.js:879:2)

Встроенные ошибки

Скопировано

SyntaxError

Скопировано

Чаще всего встречаются опечатки — неправильные названия методов, лишние или отсутствующие точки с запятой или скобочки и так далее. Такой тип ошибок называется «синтаксическим», SyntaxError:

        
          
          console.log(;)// SyntaxError: Unexpected token ';'console.log(()// SyntaxError: missing ) after argument list
          console.log(;)
// SyntaxError: Unexpected token ';'

console.log(()
// SyntaxError: missing ) after argument list

        
        
          
        
      

ReferenceError

Скопировано

Если попытаться обратиться к несуществующей переменной, произойдёт ошибка ReferenceError:

        
          
          console.log(name)// ReferenceError: name is not defined
          console.log(name)
// ReferenceError: name is not defined

        
        
          
        
      

TypeError

Скопировано

Если попытаться обратиться к несуществующему свойству, произойдёт ошибка TypeError:

        
          
          console.log(null.length)// TypeError: Cannot read property 'length' of nullundefined()// TypeError: undefined is not a function
          console.log(null.length)
// TypeError: Cannot read property 'length' of null

undefined()
// TypeError: undefined is not a function

        
        
          
        
      

RangeError

Скопировано

Ошибка для значений, которые выходят за диапазон допустимого.

        
          
          new Array(10000000000)// RangeError: Недопустимая длина массива
          new Array(10000000000)
// RangeError: Недопустимая длина массива

        
        
          
        
      

URIError

Скопировано

Этот тип ошибок возникает при неправильном использовании обработки URI.

        
          
          decodeURIComponent('%')// URIError: URI malformed
          decodeURIComponent('%')
// URIError: URI malformed

        
        
          
        
      

Валидным считается URI, формат которого соответствует спецификации RFC 3986:

URI = scheme:[//authority]path[?query][#fragment]

EvalError

Скопировано

EvalError представляет ошибку, возникающую в глобальной функции eval().

        
          
          eval(  'console.log(null.length)')
          eval(
  'console.log(null.length)'
)

        
        
          
        
      

Эта ошибка в настоящее время не используется и остаётся для совместимости с предыдущими версиями JavaScript.

InternalError (не стандарт)

Скопировано

Ошибка внутри движка JavaScript. Не является стандартом и почти не используется. Например:

"InternalError: инициализатор массива слишком большой".

Собственный класс ошибок

Скопировано

Можно расширять базовый класс Error и создавать собственные типы ошибок.

        
          
          class WrongDataTypeForSumError extends Error {  constructor(message) {    super(message)    this.name = 'WrongDataTypeForSumError'  }}const myCustomError = new WrongDataTypeForSumError('Невалидный тип данных для суммирования')
          class WrongDataTypeForSumError extends Error {
  constructor(message) {
    super(message)
    this.name = 'WrongDataTypeForSumError'
  }
}

const myCustomError = new WrongDataTypeForSumError('Невалидный тип данных для суммирования')

        
        
          
        
      

Сгенерируем ошибку WrongDataTypeForSumError в случае, если хотя бы один из аргументов функции sum — не число.

        
          
          function sum(a, b) {  if (typeof a !== 'number' || typeof b !== 'number') {    throw new WrongDataTypeForSumError('Невалидный тип данных для суммирования')  }  return a + b}console.log(sum('1', 2))// VM840:3 Uncaught WrongDataTypeForSumError: Невалидный тип данных для суммирования// at sum (<anonymous>:3:11)// at <anonymous>:9:13// WrongDataTypeForSumError @ VM830:3// sum @ VM840:3// (anonymous) @ VM840:9
          function sum(a, b) {
  if (typeof a !== 'number' || typeof b !== 'number') {
    throw new WrongDataTypeForSumError('Невалидный тип данных для суммирования')
  }

  return a + b
}

console.log(sum('1', 2))
// VM840:3 Uncaught WrongDataTypeForSumError: Невалидный тип данных для суммирования
// at sum (<anonymous>:3:11)
// at <anonymous>:9:13
// WrongDataTypeForSumError @ VM830:3
// sum @ VM840:3
// (anonymous) @ VM840:9

        
        
          
        
      

Функция будет выполняться только в том случае если оба аргумента будут числами, в противном случае функция будет возвращать ошибку WrongDataTypeForSumError.

Собственные типы ошибок делают отладку более наглядной — например из имени WrongDataTypeForSumError сразу понятно, что не так с кодом. Стандартная ошибка для таких случаев, TypeError — менее читаема.