Содержание
- Error и стандартные ошибки
- Кратко
- Как понять
- Error
- Встроенные ошибки
- SyntaxError
- ReferenceError
- TypeError
- RangeError
- URIError
- EvalError
- InternalError (не стандарт)
- Собственный класс ошибок
- Читайте также
- Выражения и инструкции
- .catch ( )
- Пользовательские ошибки, расширение Error
- Расширение Error
- Дальнейшее наследование
- Обёртывание исключений
- Итого
- Задачи
- Наследование от SyntaxError
- Перехват ошибок, «try..catch»
- Конструкция try…catch
- Объект ошибки
- Пример использования
- Генерация своих ошибок
- Оператор throw
- Проброс исключения
- Оборачивание исключений
- Секция finally
- Последняя надежда: window.onerror
- Итого
- Задачи
- Eval-калькулятор с ошибками
Error и стандартные ошибки
Какие бывают стандартные ошибки в JavaScript и как создавать собственные типы ошибок.
Время чтения: меньше 5 мин
Обновлено 31 июля 2022
Кратко
Программа может работать правильно, только если код написан корректно и не содержит ошибок. JavaScript умеет обрабатывать некорректный код и сообщать об ошибке в коде. Существует семь встроенных видов ошибок, также можно создать свои собственные. Встроенные ошибки генерируются самим движком JavaScript при выполнении программы, а пользовательские — создаются с помощью конструктора Error . Оба типа ошибок можно ловить в конструкции try . . . catch .
Как понять
Error
Общий конструктор ошибок.
Вызов конструктора возвращает объект ошибки со следующими свойствами:
- message представляет человекопонятное описание ошибки для встроенных типов ( Syntax Error , Type Error и так далее) и переданное в конструктор значение для общего типа Error .
- name — имя типа (класса) ошибки.
Нестандартное свойство stack показывает, на какой строке кода возникла ошибка. Первая строка отформатирована как : , и за ней следует серия кадров стека (каждая строка начинается с «at»).
Встроенные ошибки
SyntaxError
Чаще всего встречаются опечатки — неправильные названия методов, лишние или отсутствующие точки с запятой или скобочки и так далее. Такой тип ошибок называется «синтаксическим», Syntax Error :
ReferenceError
Если попытаться обратиться к несуществующей переменной, произойдёт ошибка Reference Error :
TypeError
Если попытаться обратиться к несуществующему свойству, произойдёт ошибка Type Error :
RangeError
Ошибка для значений, которые выходят за диапазон допустимого.
URIError
Этот тип ошибок возникает при неправильном использовании обработки URI.
Валидным считается URI, формат которого соответствует спецификации RFC 3986:
EvalError
EvalError представляет ошибку, возникающую в глобальной функции eval ( ) .
Эта ошибка в настоящее время не используется и остаётся для совместимости с предыдущими версиями JavaScript.
InternalError (не стандарт)
Ошибка внутри движка JavaScript. Не является стандартом и почти не используется. Например:
Собственный класс ошибок
Можно расширять базовый класс Error и создавать собственные типы ошибок.
Сгенерируем ошибку WrongDataTypeForSum Error в случае, если хотя бы один из аргументов функции sum — не число.
Функция будет выполняться только в том случае если оба аргумента будут числами, в противном случае функция будет возвращать ошибку WrongDataTypeForSum Error .
Собственные типы ошибок делают отладку более наглядной — например из имени WrongDataTypeForSum Error сразу понятно, что не так с кодом. Стандартная ошибка для таких случаев, Type Error — менее читаема.
Читайте также
Выражения и инструкции
Делим весь код на две группы — одна возвращает значения, другая — нет.
.catch ( )
Обрабатываем ситуации, когда обещали, но не выполнили.
Источник
Пользовательские ошибки, расширение Error
Когда что-то разрабатываем, то нам часто необходимы собственные классы ошибок для разных вещей, которые могут пойти не так в наших задачах. Для ошибок при работе с сетью может понадобиться HttpError , для операций с базой данных DbError , для поиска – NotFoundError и т.д.
Наши ошибки должны поддерживать базовые свойства, такие как message , name и, желательно, stack . Но также они могут иметь свои собственные свойства. Например, объекты HttpError могут иметь свойство statusCode со значениями 404 , 403 или 500 .
JavaScript позволяет вызывать throw с любыми аргументами, то есть технически наши классы ошибок не нуждаются в наследовании от Error . Но если использовать наследование, то появляется возможность идентификации объектов ошибок посредством obj instanceof Error . Так что лучше применять наследование.
По мере роста приложения, наши собственные ошибки образуют иерархию, например, HttpTimeoutError может наследовать от HttpError и так далее.
Расширение Error
В качестве примера рассмотрим функцию readUser(json) , которая должна читать данные пользователя в формате JSON.
Пример того, как может выглядеть корректный json :
Внутри будем использовать JSON.parse . При получении некорректного json он будет генерировать ошибку SyntaxError . Но даже если json синтаксически верен, то это не значит, что это будет корректный пользователь, верно? Могут быть пропущены необходимые данные. Например, могут отсутствовать свойства name и age , которые являются необходимыми для наших пользователей.
Наша функция readUser(json) будет не только читать JSON-данные, но и проверять их («валидировать»). Если необходимые поля отсутствуют или данные в неверном формате, то это будет ошибкой. Но не синтаксической ошибкой SyntaxError , потому что данные синтаксически корректны. Это будет другая ошибка.
Назовём её ошибкой валидации ValidationError и создадим для неё класс. Ошибка этого вида должна содержать информацию о поле, которое является источником ошибки.
Наш класс ValidationError должен наследовать от встроенного класса Error .
Класс Error встроенный, вот его примерный код, просто чтобы мы понимали, что расширяем:
Теперь давайте унаследуем от него ValidationError и попробуем новый класс в действии:
Обратите внимание: в строке (1) вызываем родительский конструктор. JavaScript требует от нас вызова super в дочернем конструкторе, так что это обязательно. Родительский конструктор устанавливает свойство message .
Родительский конструктор также устанавливает свойство name для «Error» , поэтому в строке (2) мы сбрасываем его на правильное значение.
Попробуем использовать его в readUser(json) :
Блок try..catch в коде выше обрабатывает и нашу ValidationError , и встроенную SyntaxError из JSON.parse .
Обратите внимание, как мы используем instanceof для проверки конкретного типа ошибки в строке (*) .
Мы можем также проверить тип, используя err.name :
Версия с instanceof гораздо лучше, потому что в будущем мы собираемся расширить ValidationError , сделав его подтипы, такие как PropertyRequiredError . И проверка instanceof продолжит работать для новых наследованных классов. Так что это на будущее.
Также важно, что если catch встречает неизвестную ошибку, то он пробрасывает её в строке (**) . Блок catch знает, только как обрабатывать ошибки валидации и синтаксические ошибки, а другие виды ошибок (из-за опечаток в коде и другие непонятные) он должен выпустить наружу.
Дальнейшее наследование
Класс ValidationError является слишком общим. Много что может пойти не так. Свойство может отсутствовать или иметь неверный формат (например, строка как значение возраста age ). Поэтому для отсутствующих свойств сделаем более конкретный класс PropertyRequiredError . Он будет нести дополнительную информацию о свойстве, которое отсутствует.
Новый класс PropertyRequiredError очень просто использовать: необходимо указать только имя свойства new PropertyRequiredError(property) . Сообщение для пользователя message генерируется конструктором.
Обратите внимание, что свойство this.name в конструкторе PropertyRequiredError снова присвоено вручную. Правда, немного утомительно – присваивать this.name = в каждом классе пользовательской ошибки. Можно этого избежать, если сделать наш собственный «базовый» класс ошибки, который будет ставить this.name = this.constructor.name . И затем наследовать все ошибки уже от него.
Давайте назовём его MyError .
Вот упрощённый код с MyError и другими пользовательскими классами ошибок:
Теперь пользовательские ошибки стали намного короче, особенно ValidationError , так как мы избавились от строки «this.name = . » в конструкторе.
Обёртывание исключений
Назначение функции readUser в приведённом выше коде – это «чтение данных пользователя». В процессе могут возникнуть различные виды ошибок. Сейчас у нас есть SyntaxError и ValidationError , но в будущем функция readUser может расшириться и, возможно, генерировать другие виды ошибок.
Код, который вызывает readUser , должен обрабатывать эти ошибки.
Сейчас в нём используются проверки if в блоке catch , которые проверяют класс и обрабатывают известные ошибки и пробрасывают дальше неизвестные. Но если функция readUser генерирует несколько видов ошибок, то мы должны спросить себя: действительно ли мы хотим проверять все типы ошибок поодиночке во всех местах в коде, где вызывается readUser ?
Часто ответ «Нет»: внешний код хочет быть на один уровень выше всего этого. Он хочет иметь какую-то обобщённую ошибку чтения данных. Почему именно это произошло – часто не имеет значения (об этом говорится в сообщении об ошибке). Или даже лучше, если есть способ получить подробности об ошибке, но только если нам это нужно.
Итак, давайте создадим новый класс ReadError для представления таких ошибок. Если ошибка возникает внутри readUser , мы её перехватим и сгенерируем ReadError . Мы также сохраним ссылку на исходную ошибку в свойстве cause . Тогда внешний код должен будет только проверить наличие ReadError .
Этот код определяет ошибку ReadError и демонстрирует её использование в readUser и try..catch :
В приведённом выше коде readUser работает так, как описано – функция распознаёт синтаксические ошибки и ошибки валидации и выдаёт вместо них ошибки ReadError (неизвестные ошибки, как обычно, пробрасываются).
Внешний код проверяет только instanceof ReadError . Не нужно перечислять все возможные типы ошибок
Этот подход называется «обёртывание исключений», потому что мы берём «исключения низкого уровня» и «оборачиваем» их в ReadError , который является более абстрактным и более удобным для использования в вызывающем коде. Такой подход широко используется в объектно-ориентированном программировании.
Итого
- Мы можем наследовать свои классы ошибок от Error и других встроенных классов ошибок, но нужно позаботиться о свойстве name и не забыть вызвать super .
- Мы можем использовать instanceof для проверки типа ошибок. Это также работает с наследованием. Но иногда у нас объект ошибки, возникшей в сторонней библиотеке, и нет простого способа получить класс. Тогда для проверки типа ошибки можно использовать свойство name .
- Обёртывание исключений является распространённой техникой: функция ловит низкоуровневые исключения и создаёт одно «высокоуровневое» исключение вместо разных низкоуровневых. Иногда низкоуровневые исключения становятся свойствами этого объекта, как err.cause в примерах выше, но это не обязательно.
Задачи
Наследование от SyntaxError
Создайте класс FormatError , который наследует от встроенного класса SyntaxError .
Класс должен поддерживать свойства message , name и stack .
Источник
Перехват ошибок, «try..catch»
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/try-catch.
Как бы мы хорошо ни программировали, в коде бывают ошибки. Или, как их иначе называют, «исключительные ситуации» (исключения).
Обычно скрипт при ошибке, как говорят, «падает», с выводом ошибки в консоль.
Но бывают случаи, когда нам хотелось бы как-то контролировать ситуацию, чтобы скрипт не просто «упал», а сделал что-то разумное.
Для этого в JavaScript есть замечательная конструкция try..catch .
Конструкция try…catch
Конструкция try..catch состоит из двух основных блоков: try , и затем catch :
Работает она так:
Выполняется код внутри блока try .
Если в нём ошибок нет, то блок catch(err) игнорируется, то есть выполнение доходит до конца try и потом прыгает через catch .
Если в нём возникнет ошибка, то выполнение try на ней прерывается, и управление прыгает в начало блока catch(err) .
При этом переменная err (можно выбрать и другое название) будет содержать объект ошибки с подробной информацией о произошедшем.
Таким образом, при ошибке в try скрипт не «падает», и мы получаем возможность обработать ошибку внутри catch .
Посмотрим это на примерах.
Пример без ошибок: при запуске сработают alert (1) и (2) :
Пример с ошибкой: при запуске сработают (1) и (3) :
Если грубо нарушена структура кода, например не закрыта фигурная скобка или где-то стоит лишняя запятая, то никакой try..catch здесь не поможет. Такие ошибки называются синтаксическими, интерпретатор не может понять такой код.
Здесь же мы рассматриваем ошибки семантические, то есть происходящие в корректном коде, в процессе выполнения.
Ошибку, которая произойдёт в коде, запланированном «на будущее», например в setTimeout , try..catch не поймает:
На момент запуска функции, назначенной через setTimeout , этот код уже завершится, интерпретатор выйдет из блока try..catch .
Чтобы поймать ошибку внутри функции из setTimeout , и try..catch должен быть в той же функции.
Объект ошибки
В примере выше мы видим объект ошибки. У него есть три основных свойства:
name Тип ошибки. Например, при обращении к несуществующей переменной: «ReferenceError» . message Текстовое сообщение о деталях ошибки. stack Везде, кроме IE8-, есть также свойство stack , которое содержит строку с информацией о последовательности вызовов, которая привела к ошибке.
В зависимости от браузера у него могут быть и дополнительные свойства, см. Error в MDN и Error в MSDN.
Пример использования
В JavaScript есть встроенный метод JSON.parse(str), который используется для чтения JavaScript-объектов (и не только) из строки.
Обычно он используется для того, чтобы обрабатывать данные, полученные по сети, с сервера или из другого источника.
Мы получаем их и вызываем метод JSON.parse , вот так:
Более детально формат JSON разобран в главе Формат JSON, метод toJSON.
В случае, если данные некорректны, JSON.parse генерирует ошибку, то есть скрипт «упадёт».
Устроит ли нас такое поведение? Конечно нет!
Получается, что если вдруг что-то не так с данными, то посетитель никогда (если, конечно, не откроет консоль) об этом не узнает.
А люди очень-очень не любят, когда что-то «просто падает», без всякого объявления об ошибке.
Бывают ситуации, когда без try..catch не обойтись, это – одна из таких.
Используем try..catch , чтобы обработать некорректный ответ:
Здесь в alert только выводится сообщение, но область применения гораздо шире: можно повторять запрос, можно предлагать посетителю использовать альтернативный способ, можно отсылать информацию об ошибке на сервер… Свобода действий.
Генерация своих ошибок
Представим на минуту, что данные являются корректным JSON… Но в этом объекте нет нужного свойства name :
Вызов JSON.parse выполнится без ошибок, но ошибка в данных есть. И, так как свойство name обязательно должно быть, то для нас это такие же некорректные данные, как и «Has Error» .
Для того, чтобы унифицировать и объединить обработку ошибок парсинга и ошибок в структуре, мы воспользуемся оператором throw .
Оператор throw
Оператор throw генерирует ошибку.
Технически в качестве объекта ошибки можно передать что угодно, это может быть даже не объект, а число или строка, но всё же лучше, чтобы это был объект, желательно – совместимый со стандартным, то есть чтобы у него были как минимум свойства name и message .
В качестве конструктора ошибок можно использовать встроенный конструктор: new Error(message) или любой другой.
В JavaScript встроен ряд конструкторов для стандартных ошибок: SyntaxError , ReferenceError , RangeError и некоторые другие. Можно использовать и их, но только чтобы не было путаницы.
В данном случае мы используем конструктор new SyntaxError(message) . Он создаёт ошибку того же типа, что и JSON.parse .
Получилось, что блок catch – единое место для обработки ошибок во всех случаях: когда ошибка выявляется при JSON.parse или позже.
Проброс исключения
В коде выше мы предусмотрели обработку ошибок, которые возникают при некорректных данных. Но может ли быть так, что возникнет какая-то другая ошибка?
Конечно, может! Код – это вообще мешок с ошибками, бывает даже так, что библиотеку выкладывают в открытый доступ, она там 10 лет лежит, её смотрят миллионы людей и на 11-й год находятся опаснейшие ошибки. Такова жизнь, таковы люди.
Блок catch в нашем примере предназначен для обработки ошибок, возникающих при некорректных данных. Если же в него попала какая-то другая ошибка, то вывод сообщения о «некорректных данных» будет дезинформацией посетителя.
Ошибку, о которой catch не знает, он не должен обрабатывать.
Такая техника называется «проброс исключения»: в catch(e) мы анализируем объект ошибки, и если он нам не подходит, то делаем throw e .
При этом ошибка «выпадает» из try..catch наружу. Далее она может быть поймана либо внешним блоком try..catch (если есть), либо «повалит» скрипт.
В примере ниже catch обрабатывает только ошибки SyntaxError , а остальные – выбрасывает дальше:
Заметим, что ошибка, которая возникла внутри блока catch , «выпадает» наружу, как если бы была в обычном коде.
В следующем примере такие ошибки обрабатываются ещё одним, «более внешним» try..catch :
В примере выше try..catch внутри readData умеет обрабатывать только SyntaxError , а внешний – все ошибки.
Без внешнего проброшенная ошибка «вывалилась» бы в консоль с остановкой скрипта.
Оборачивание исключений
И, для полноты картины – последняя, самая продвинутая техника по работе с ошибками. Она, впрочем, является стандартной практикой во многих объектно-ориентированных языках.
Цель функции readData в примере выше – прочитать данные. При чтении могут возникать разные ошибки, не только SyntaxError , но и, возможно, к примеру URIError (неправильное применение функций работы с URI) да и другие.
Код, который вызвал readData , хотел бы иметь либо результат, либо информацию об ошибке.
При этом очень важным является вопрос: обязан ли этот внешний код знать о всевозможных типах ошибок, которые могут возникать при чтении данных, и уметь перехватывать их?
Обычно внешний код хотел бы работать «на уровень выше», и получать либо результат, либо «ошибку чтения данных», при этом какая именно ошибка произошла – ему неважно. Ну, или, если будет важно, то хотелось бы иметь возможность это узнать, но обычно не требуется.
Это важнейший общий подход к проектированию – каждый участок функциональности должен получать информацию на том уровне, который ей необходим.
Мы его видим везде в грамотно построенном коде, но не всегда отдаём себе в этом отчёт.
В данном случае, если при чтении данных происходит ошибка, то мы будем генерировать её в виде объекта ReadError , с соответствующим сообщением. А «исходную» ошибку на всякий случай тоже сохраним, присвоим в свойство cause (англ. – причина).
Выглядит это так:
Этот подход называют «оборачиванием» исключения, поскольку мы берём ошибки «более низкого уровня» и «заворачиваем» их в ReadError , которая соответствует текущей задаче.
Секция finally
Конструкция try..catch может содержать ещё один блок: finally .
Выглядит этот расширенный синтаксис так:
Секция finally не обязательна, но если она есть, то она выполняется всегда:
- после блока try , если ошибок не было,
- после catch , если они были.
Попробуйте запустить такой код?
У него два варианта работы:
- Если вы ответите на вопрос «сгенерировать ошибку?» утвердительно, то try -> catch -> finally .
- Если ответите отрицательно, то try -> finally .
Секцию finally используют, чтобы завершить начатые операции при любом варианте развития событий.
Например, мы хотим подсчитать время на выполнение функции sum(n) , которая должна возвратить сумму чисел от 1 до n и работает рекурсивно:
Здесь секция finally гарантирует, что время будет подсчитано в любых ситуациях: при ошибке в sum или без неё.
Вы можете проверить это, запустив код с указанием n=100 – будет без ошибки, finally выполнится после try , а затем с n=100000 – будет ошибка из-за слишком глубокой рекурсии, управление прыгнет в finally после catch .
Блок finally срабатывает при любом выходе из try..catch , в том числе и return .
В примере ниже из try происходит return , но finally получает управление до того, как контроль возвращается во внешний код.
Если внутри try были начаты какие-то процессы, которые нужно завершить по окончании работы, то в finally это обязательно будет сделано.
Кстати, для таких случаев иногда используют try..finally вообще без catch :
В примере выше try..finally вообще не обрабатывает ошибки. Задача в другом: выполнить код при любом выходе из try – с ошибкой ли, без ошибок или через return .
Последняя надежда: window.onerror
Допустим, ошибка произошла вне блока try..catch или выпала из try..catch наружу, во внешний код. Скрипт упал.
Можно ли как-то узнать о том, что произошло? Да, конечно.
В браузере существует специальное свойство window.onerror , если в него записать функцию, то она выполнится и получит в аргументах сообщение ошибки, текущий URL и номер строки, откуда «выпала» ошибка.
Необходимо лишь позаботиться, чтобы функция была назначена заранее.
Как правило, роль window.onerror заключается не в том, чтобы оживить скрипт – скорее всего, это уже невозможно, а в том, чтобы отослать сообщение об ошибке на сервер, где разработчики о ней узнают.
Существуют даже специальные веб-сервисы, которые предоставляют скрипты для отлова и аналитики таких ошибок, например: https://errorception.com/ или https://www.muscula.com/.
Итого
Обработка ошибок – большая и важная тема.
В JavaScript для этого предусмотрены:
Конструкция try..catch..finally – она позволяет обработать произвольные ошибки в блоке кода.
Это удобно в тех случаях, когда проще сделать действие и потом разбираться с результатом, чем долго и нудно проверять, не упадёт ли чего.
Кроме того, иногда проверить просто невозможно, например JSON.parse(str) не позволяет «проверить» формат строки перед разбором. В этом случае блок try..catch необходим.
Полный вид конструкции:
Возможны также варианты try..catch или try..finally .
Оператор throw err генерирует свою ошибку, в качестве err рекомендуется использовать объекты, совместимые с встроенным типом Error, содержащие свойства message и name .
Кроме того, мы рассмотрели некоторые важные приёмы:
Проброс исключения – catch(err) должен обрабатывать только те ошибки, которые мы рассчитываем в нём увидеть, остальные – пробрасывать дальше через throw err .
Определить, нужная ли это ошибка, можно, например, по свойству name .
Оборачивание исключений – функция, в процессе работы которой возможны различные виды ошибок, может «обернуть их» в одну общую ошибку, специфичную для её задачи, и уже её пробросить дальше. Чтобы при необходимости можно было подробно определить, что произошло, исходную ошибку обычно присваивают в свойство этой, общей. Обычно это нужно для логирования.
В window.onerror можно присвоить функцию, которая выполнится при любой «выпавшей» из скрипта ошибке. Как правило, это используют в информационных целях, например отправляют информацию об ошибке на специальный сервис.
Задачи
Eval-калькулятор с ошибками
Напишите интерфейс, который принимает математическое выражение (в prompt ) и выводит результат его вычисления через eval .
При ошибке нужно выводить сообщение и просить переввести выражение.
Ошибкой считается не только некорректное выражение, такое как 2+ , но и выражение, возвращающее NaN , например 0/0 .
Вычислить любое выражение нам поможет eval :
Источник
На чтение 5 мин Просмотров 3.9к. Опубликовано 03.01.2021
В этом руководстве мы рассмотрим как используется и для чего нужны исключения (exception) в Python. Так же рассмотрим как использовать конструкцию try-except.
Содержание
- Введение
- Примеры вызова exception
- Получение доступа к индексу за пределами списка
- Конвертирование неподходящего типа
- Обращение к несуществующей переменной
- Смешивание типов без преобразования
- Типы исключений
- Обработка всех исключений
- Обработка конкретных исключений
- Обработка нескольких исключений
- Использование оператора finally
- Заключение
Введение
Для управления ошибками, которые появляются в программе, Python использует особые объекты, называемые исключениями (exceptions).
Каждый раз, когда происходит ошибка, из-за которой Python не знает, что делать дальше, создается объект исключения. Если напишете код, обрабатывающий исключение, то приложение не завершит работу, а продолжит выполнение. Не написав обработку исключения программа остановится и покажет трассировку, которая включает в себя отчет об ошибке.
Примеры вызова exception
Рассмотрим популярные примеры вызов исключений.
Получение доступа к индексу за пределами списка
num = [33,34, 35, 36] num[7] IndexError: list index out of range
Конвертирование неподходящего типа
dict(num) TypeError: cannot convert dictionary update sequence element #0 to a sequence
Обращение к несуществующей переменной
print(city) NameError: name 'city' is not defined
Смешивание типов без преобразования
a = 'test string' a + 10 TypeError: can only concatenate str (not "int") to str
Типы исключений
- SyntaxError — Ошибка в синтаксисе программы
- NameError — Ошибка обращения к несуществующей переменной
- AttributeError — Ссылка на атрибут не работает
- TypeError — Операнд не имеет правильного типа
- ValueError — Неверный тип у значения переменной
- IOError — Ошибка в подсистеме системе ввода вывода
- ZeroDivisionError — Ошибка деления на ноль
Ознакомиться с полным списком встроенных исключений можно в официальной документации.
first = int(input("Напишите любое целое число: "))
second = int(input("Введите еще одно число: "))
print(first/second)
Этот пример кода выполняет деление одного числа на другое. Чтобы продемонстрировать ошибку, предположим что пользователь вводит 10 и 0 в качестве первого и второго чисел соответственно, Python на это возбуждает исключение ZeroDivisionError:
Напишите любое целое число: 10 Введите еще одно число: 0 ZeroDivisionError: division by zero
Обработка всех исключений
Язык имеет встроенную конструкцию для работы с исключениями. Обработка происходит с помощью блока try-except.
Блок try-except заставляет Python выполнить код внутри него, но также говорит Python, что делать в случае если будет вызвано исключение. Когда используете try-except, программа будет продолжать работать, даже если возникнут какие-нибудь ошибки. Вместо Traceback, который сбивает с толку, пользователи увидят дружественные сообщения об ошибках, но их нужно заранее предусмотреть.
try:
first = int(input("Напишите любое целое число: "))
second = int(input("Введите еще одно число: "))
print(first/second)
except:
print("Ошибка ввода данных")
Давайте введем тот же набор данных что и посмотрим что будет
Напишите любое целое число: 10 Введите еще одно число: 0 Ошибка ввода данных
Ввод строки вместо числа
Напишите любое целое число: 10 Введите еще одно число: ноль Ошибка ввода данных
В предыдущем примере деление на 0 приводило к исключению ZeroDivisionError, но когда ввели строковое значение переменной и попробовали на него разделить число сработало новое исключение ValueError.
Проверка с корректным вводом.
Напишите любое целое число: 6 Введите еще одно число: 2 3
В этом примере не происходит вызова исключений т.к данные введены и обработаны корректно.
Обработка конкретных исключений
В предыдущем примере использовался обработчик на все возникающие исключения. Но такой вариант использования не рекомендуется, будут заглушены ошибки, возникающие по непредвиденным обстоятельствам.
В нашем случае можно поймать и обработать исключение ZeroDivisionError.
try:
first = int(input("Напишите любое целое число: "))
second = int(input("Введите еще одно число: "))
print(first/second)
except ZeroDivisionError:
print("Разделить число на ноль - невозможно!")
Попробуем разделить на ноль и посмотрим результат
Напишите любое целое число: 4 Введите еще одно число: 0 Разделить число на ноль - невозможно!
А что будет если ввести строку?
Напишите любое целое число: 4 Введите еще одно число: один ValueError: invalid literal for int() with base 10: 'один'
Python вызывает исключения, потому что мы не написали код для этого конкретного исключения — ValueError.
Обработка нескольких исключений
Конструкция обработки исключений дает возможность обрабатывать каждый тип ошибки отдельно, пример ниже дополнительно обрабатывает ошибку ValueError
try:
first = int(input("Напишите любое целое число: "))
second = int(input("Введите еще одно число: "))
print(first/second)
except ZeroDivisionError:
print("Разделить число на ноль - невозможно!")
except ValueError:
print("Неправильный тип переменной")
Использование оператора finally
В конструкции try-except есть дополнительный, но не обязательный оператор finally. Код внутри этого блока выполняется перед завершением конструкции try-except, вне зависимости от того какие исключения были обработаны, а какие нет.
try:
first = int(input("Напишите любое целое число: "))
second = int(input("Введите еще одно число: "))
print(first/second)
except ZeroDivisionError:
print("Разделить число на ноль - невозможно!")
except ValueError:
print("Неправильный тип переменной")
finally:
print("Работа программы завершена")
В реальных приложениях, выражение finally полезно для освобождения внешних ресурсов (таких, как файлы или сетевые соединения), независимо от того, было ли использование ресурса успешным.
Заключение
Сегодня мы рассмотрели как используется и для чего нужны исключения в Python. Если у вас есть дополнительные вопросы, не стесняйтесь задавать их в комментариях.
Содержание
- Error и стандартные ошибки
- Кратко
- Как понять
- Error
- Встроенные ошибки
- SyntaxError
- ReferenceError
- TypeError
- RangeError
- URIError
- EvalError
- InternalError (не стандарт)
- Собственный класс ошибок
- Читайте также
- Выражения и инструкции
- .catch ( )
- JavaScript: Ошибки при работе с переменными
- Задание
- Определения
- Как расшифровать ошибки Uncaught ReferenceError, Uncaught Error, Uncaught TypeError и т.д
- 2 ответа 2
- Топ-10 ошибок из 1000+ JavaScript-проектов и рекомендации по их устранению
- Методика анализа
- 1. Uncaught TypeError: Cannot read property
- 2. TypeError: ‘undefined’ is not an object (evaluating…
- 3. TypeError: null is not an object (evaluating
- 4. (unknown): Script error
Error и стандартные ошибки
Какие бывают стандартные ошибки в JavaScript и как создавать собственные типы ошибок.
Время чтения: меньше 5 мин
Обновлено 31 июля 2022
Кратко
Программа может работать правильно, только если код написан корректно и не содержит ошибок. JavaScript умеет обрабатывать некорректный код и сообщать об ошибке в коде. Существует семь встроенных видов ошибок, также можно создать свои собственные. Встроенные ошибки генерируются самим движком JavaScript при выполнении программы, а пользовательские — создаются с помощью конструктора Error . Оба типа ошибок можно ловить в конструкции try . . . catch .
Как понять
Error
Общий конструктор ошибок.
Вызов конструктора возвращает объект ошибки со следующими свойствами:
- message представляет человекопонятное описание ошибки для встроенных типов ( Syntax Error , Type Error и так далее) и переданное в конструктор значение для общего типа Error .
- name — имя типа (класса) ошибки.
Нестандартное свойство stack показывает, на какой строке кода возникла ошибка. Первая строка отформатирована как : , и за ней следует серия кадров стека (каждая строка начинается с «at»).
Встроенные ошибки
SyntaxError
Чаще всего встречаются опечатки — неправильные названия методов, лишние или отсутствующие точки с запятой или скобочки и так далее. Такой тип ошибок называется «синтаксическим», Syntax Error :
ReferenceError
Если попытаться обратиться к несуществующей переменной, произойдёт ошибка Reference Error :
TypeError
Если попытаться обратиться к несуществующему свойству, произойдёт ошибка Type Error :
RangeError
Ошибка для значений, которые выходят за диапазон допустимого.
URIError
Этот тип ошибок возникает при неправильном использовании обработки URI.
Валидным считается URI, формат которого соответствует спецификации RFC 3986:
EvalError
EvalError представляет ошибку, возникающую в глобальной функции eval ( ) .
Эта ошибка в настоящее время не используется и остаётся для совместимости с предыдущими версиями JavaScript.
InternalError (не стандарт)
Ошибка внутри движка JavaScript. Не является стандартом и почти не используется. Например:
Собственный класс ошибок
Можно расширять базовый класс Error и создавать собственные типы ошибок.
Сгенерируем ошибку WrongDataTypeForSum Error в случае, если хотя бы один из аргументов функции sum — не число.
Функция будет выполняться только в том случае если оба аргумента будут числами, в противном случае функция будет возвращать ошибку WrongDataTypeForSum Error .
Собственные типы ошибок делают отладку более наглядной — например из имени WrongDataTypeForSum Error сразу понятно, что не так с кодом. Стандартная ошибка для таких случаев, Type Error — менее читаема.
Читайте также
Выражения и инструкции
Делим весь код на две группы — одна возвращает значения, другая — нет.
.catch ( )
Обрабатываем ситуации, когда обещали, но не выполнили.
Источник
JavaScript: Ошибки при работе с переменными
Порядок следования инструкций в коде с переменными играет огромное значение. Переменная должна быть определена до того, как будет использована. Ниже пример ошибки, которую очень часто допускают новички:
Запуск программы с примера выше завершается ошибкой ReferenceError: greeting is not defined. ReferenceError — это ошибка обращения, она означает, что в коде используется имя (говорят идентификатор), которое не определено. Причём в самой ошибке об этом говорят прямо: greeting is not defined, что переводится как greeting не определен. Кроме неправильного порядка определения, в JavaScript встречаются банальные опечатки — как при использовании переменной, так и при её объявлении.
Количество подобных ошибок уменьшается за счет использования правильно настроенного редактора. Такой редактор подсвечивает имена, которые используются без объявления и предупреждает о возможных проблемах.
Еще одна распространенная ошибка — попытаться объявить уже объявленную переменную:
Так делать нельзя. Придётся создать новую переменную.
Задание
Найдите в программе необъявленную переменную и объявите ее, присвоив ей значение ‘Dragon’;
После выполнения программы результат на экране должен выглядеть так:
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Определения
Переменная — способ сохранить информацию и дать ей имя для последующего использования в коде.
Источник
Как расшифровать ошибки Uncaught ReferenceError, Uncaught Error, Uncaught TypeError и т.д
Подскажите пожалуйста, как расшифровать данные ошибки по порядку? О чем говорит наличие этих ошибок?
2 ответа 2
- GET ошибка, браузерскрипт, обращается к файлу на сервере, которого не существует, либо указан неверный url , что привело к 404 ошибке net::ERROR_FILE_NOT_FOUND .
- Uncaught ReferenceError: jQuery is not defined , Uncaught — означает выброшенное исключение(ошибка), не была «поймана»(обработана), с помощью конструкции try-catch . Она говорит, что вы пытаетесь обратиться к несуществующей( is not defined ) переменной jQuery . Скорее всего эта ошибка была вызвана тем, что у вас jQuery подключается после скрипта, в котором вызывается jQuery .
- Uncaught Error: Bootstrap’s JavaScript requires jQuery : вы подключили JavaScript файл bootstrap , но подключили его до jQuery , и в JavaScript файле bootstrap сработал конструкция try-catch и выбросила вам исключение, о том что jQuery должен быть подключен до bootstrap JavaScript файла. (Так же try-catch выдала вам сообщение об ошибке, которое может изменяться, а может быть и по умолчанию).
- Uncaught ReferenceError: jQuery is not defined : Уже описывал выше.
- Uncaugth TypeError: Cannot read property ‘fn’ of undefined : в данном случае скрипт пытается обратиться к объекту foo и получить его параметр fn , вот так: foo.fn , скорее всего это опять же из-за порядка подключения js файлов, именно из-за того, что библиотека daterangepicker использует jQuery , но jQuery не был подключен до текущего скрипта, что скорее всего привело объект foo как неопределенный undefined .
- Uncaught ReferenceError: jQuery is not defined : Уже описывал выше.
- Uncaught ReferenceError: jQuery is not defined : Уже описывал выше.
Внимательно посмотрите порядок подключения скриптов. Браузер считывает последовательно, друг за другом, есть конечно дополнительные атрибуты для подключения скриптов(async и defer). Попробуйте перенести подключение jQuery выше всех остальных скриптов, и посмотрите что случится :).
Источник
Топ-10 ошибок из 1000+ JavaScript-проектов и рекомендации по их устранению
В компании Rollbar, которая занимается созданием инструментов для работы с ошибками в программах, решили проанализировать базу из более чем 1000 проектов на JavaScript и найти в них ошибки, которые встречаются чаще всего. В результате они сформировали список из 10 наиболее часто встречающихся ошибок, проанализировали причины их появления и рассказали о том, как их исправлять и избегать. Они полагают, что знакомство с этими ошибками поможет JS-разработчикам писать более качественный код.
Методика анализа
В наши дни данные — это всё, поэтому мы нашли, проанализировали и проранжировали ошибки, которые чаще всего встречаются в JavaScript-проектах. А именно, были собраны сведения об ошибках по каждому проекту, после чего было подсчитано количество ошибок каждого вида. Ошибки группировались по их контрольной сумме, методику вычисления которой можно найти здесь. При таком подходе, если, например, в одном проекте обнаружена некая ошибка, которая после этого найдена где-то ещё, такие ошибки группируют. Это позволяет, после анализа всех участвующих в исследовании проектов, получить краткую сводку по ошибкам, а не нечто вроде огромного лог-файла, с которым неудобно работать.
В ходе исследования особое внимание уделялось наиболее часто встречающимся ошибкам. Для того чтобы такие ошибки отобрать, их ранжировали по количеству проектов разных компаний, в которых они встречаются. Если бы в этот рейтинг входило лишь общее число появлений некоей ошибки, то ошибки, характерные для какого-нибудь очень крупного проекта, но редко встречающиеся в других проектах, исказили бы результаты.
Вот десять ошибок, которые были отобраны по результатам исследования. Они отсортированы по количеству проектов, в которых они встречаются.
Ошибки, которые встречаются в JS-проектах чаще всего
Названия ошибок представляют собой сокращённый вариант сообщения об ошибке, которое выдаёт система. Опора на системные сообщения позволяет легко идентифицировать ошибки при их возникновении. Сейчас мы проанализируем каждую из них, расскажем о том, что их вызывает, и о том, как с ними бороться.
1. Uncaught TypeError: Cannot read property
Если вы пишете программы на JavaScript, то вы, вероятно, встречались с этой ошибкой гораздо чаще, чем вам того хотелось бы. Подобная ошибка возникает, например, в Google Chrome при попытке прочитать свойство или вызвать метод неопределённой переменной, то есть той, которая имеет значение undefined . Увидеть эту ошибку в действии можно с помощью консоли инструментов разработчика Chrome.
Ошибка Cannot read property
Эта ошибка может возникнуть по многим причинам, но чаще всего её вызывает неправильная инициализация состояния при рендеринге элемента пользовательского интерфейса. Взглянем на пример того, как подобное может произойти в реальном приложении. Тут мы используем React, но та же ошибка инициализации характерна для Angular, Vue и для любых других фреймворков.
Тут надо обратить внимание на две важные вещи:
- В самом начале состояние компонента (то есть — this.state ) представлено значением undefined .
- При асинхронной загрузке данных компонент будет выведен как минимум один раз до того, как данные будут загружены, вне зависимости от того, будет ли это выполнено в componentWillMount или в componentDidMount . Когда элемент Quiz выводится в первый раз, в this.state.items записано undefined . Это, в свою очередь, означает, что itemList получает элементы, которые так же представлены значением undefined . Как результат, мы видим в консоли следующую ошибку: «Uncaught TypeError: Cannot read property ‘map’ of undefined» .
Эту ошибку исправить несложно. Проще всего инициализировать состояние в конструкторе подходящими значениями по умолчанию.
Код вашего приложения будет выглядеть иначе, но мы надеемся, что теперь вы знаете, как исправить эту ошибку в своём проекте и как избежать её появления. Если то, о чём шла речь, вам не подходит — возможно, вам поможет разбор следующих ошибок.
2. TypeError: ‘undefined’ is not an object (evaluating…
Эта ошибка возникает в браузере Safari при попытке прочесть свойство или вызвать метод неопределённого объекта. Взглянуть на эту ошибку можно с помощью консоли инструментов разработчика Safari. На самом деле, тут перед нами та же самая проблема, которую мы разбирали выше для Chrome, но в Safari она приводит к другому сообщению об ошибке.
Ошибка ‘undefined’ is not an object
Исправлять эту ошибку надо так же, как в предыдущем примере.
3. TypeError: null is not an object (evaluating
Эта ошибка возникает в Safari при попытке обратиться к методу или свойству переменной, представленной значением null . Вот как это выглядит в консоли разработчика Safari.
Ошибка TypeError: null is not an object
Напомним, что в JavaScript null и undefined — это не одно и то же, именно поэтому мы видим разные сообщения об ошибках. Смысл значения undefined , записанного в переменную, говорит о том, что переменной не назначено никакого значения, а null указывает на пустое значение. Для того чтобы убедиться в том, что null не равно undefined , можно сравнить их с использованием оператора строгого равенства:
Сравнение undefined и null с помощью операторов нестрогого и строгого равенства
Одна из причин возникновения подобной ошибки в реальных приложениях заключается в попытке использования элемента DOM в JavaScript до загрузки элемента. Происходит это из-за того, что DOM API возвращает null для ссылок на пустые объекты.
Любой JS-код, который работает с элементами DOM, должен выполняться после создания элементов DOM. Интерпретация JS-кода производится сверху вниз по мере появления его в HTML-документе. Поэтому если тег
4. (unknown): Script error
Эта ошибка возникает в том случае, когда неперехваченная ошибка JavaScript пересекает границы доменов при нарушении политики кросс-доменных ограничений. Например, если ваш JS-код размещён на CDN-ресурсе, в сообщении о любой неперехваченной ошибке (то есть, об ошибке, которая не перехвачена в блоке try-catch и дошла до обработчика window.onerror ) будет указано Script error , а не полезная для целей устранения этой ошибки информация. Это — один из браузерных механизмов безопасности, направленный на предотвращение передачи данных между фрагментами кода, источниками которого являются разные домены, и которым в обычных условиях запрещено обмениваться информацией.
Вот последовательность действий, которая поможет увидеть эту ошибку.
1. Отправка заголовка Access-Control-Allow-Origin .
Установка заголовка Access-Control-Allow-Origin в состояние * указывает на то, что к ресурсу можно получить доступ из любого домена.
Знак звёздочки можно, при необходимости, заменить на конкретный домен, например так : Access-Control-Allow-Origin: www.example.com . Однако поддержка нескольких доменов — дело довольно сложное. Такая поддержка может не стоить затраченных на её обеспечение усилий, если вы используете CDN, из-за возможного возникновения проблем с кэшированием. Подробности об этом можно посмотреть здесь.
Вот примеры установки этого заголовка в различных окружениях.
В папке, из которой будут загружаться ваши JavaScript-файлы, создайте файл .htaccess со следующим содержимым:
Добавьте директиву add_header к блоку location , который отвечает за обслуживание ваших JS-файлов:
Добавьте следующую настройку к параметрам системы, ответственной за поддержку JS-файлов:
2. Установите crossorigin=»anonymous» в теге
Источник
Существует ряд причин, по которым код JavaScript может вызывать ошибки, например:
- Проблема с сетевым подключением;
- Пользователь мог ввести неверное значение в поля формы;
- Ссылка на объекты или функции, которые не существуют;
- Неправильные данные отправляются или принимаются с веб-сервера;
- Служба, к которой приложение должно получить доступ, может быть временно недоступна.
Эти типы ошибок известны как ошибки времени выполнения (runtime errors), поскольку они возникают во время выполнения скрипта. Профессиональное приложение должно иметь возможность корректно обрабатывать такие ошибки во время выполнения. Обычно это означает понятное информирование пользователя о возникшей проблеме.
Оператор try…catch
JavaScript предоставляет оператор try-catch, чтобы перехватывать ошибки времени выполнения и корректно их обработать.
Любой код, который может вызвать ошибку, должен быть помещен в блок оператора try, а код для обработки ошибки помещен в блок catch, как показано здесь:
try {
// Код, который может вызвать ошибку
} catch(error) {
// Действие, которое нужно выполнить при возникновении ошибки
}
Если ошибка возникает в любой точке блока try, выполнение кода немедленно переносится из блока try в блок catch. Если в блоке try ошибки не возникает, блок catch будет проигнорирован, и программа продолжит выполнение после оператора try-catch.
Следующий пример демонстрирует, как работает оператор try-catch:
try {
var greet = "Hi, there!";
document.write(greet);
// Попытка получить доступ к несуществующей переменной
document.write(welcome);
// Если произошла ошибка, следующая строка не будет выполнена
alert("All statements are executed successfully.");
} catch(error) {
// Обработка ошибки
alert("Caught error: " + error.message);
}
// Продолжаем исполнение кода
document.write("<p>Hello World!</p>");
Приведенный выше скрипт генерирует ошибку, которая отображается в диалоговом окне с предупреждением, а не выводится в консоль браузера. Кроме того, программа не остановилась внезапно, даже если произошла ошибка.
Также обратите внимание, что за ключевым словом catch указывается идентификатор в скобках. Этот идентификатор действует как параметр функции. При возникновении ошибки интерпретатор JavaScript генерирует объект, содержащий сведения о нем. Этот объект ошибки затем передается в качестве аргумента для обработки.
Оператор try-catch является механизмом обработки исключений. Исключением является сигнал, который указывает, что во время выполнения программы возникли какие-то исключительные условия или ошибки. Термины «исключение» и «ошибка» часто используются взаимозаменяемо.
Оператор try…catch…finally
Оператор try-catch также может содержать предложение finally. Код внутри блока finally всегда будет выполняться независимо от того, произошла ошибка в блоке try или нет.
В следующем примере всегда отображается общее время, затраченное на выполнение кода.
// Присвоение значения, возвращаемого диалоговым окном
var num = prompt("Enter a positive integer between 0 to 100");
// Запоминание времени начала исполнения
var start = Date.now();
try {
if(num > 0 && num <= 100) {
alert(Math.pow(num, num)); // the base to the exponent power
} else {
throw new Error("An invalid value is entered!");
}
} catch(e) {
alert(e.message);
} finally {
// Отображение времени, необходимого для выполнения кода
alert("Execution took: " + (Date.now() - start) + "ms");
}
Вызов ошибок с помощью оператора throw
До сих пор мы видели ошибки, которые автоматически генерируются парсером JavaScript. Тем не менее, также можно вызвать ошибку вручную с помощью оператора throw.
Общий синтаксис оператора throw: throw expression;
Выражение expression может быть объектом или значением любого типа данных. Однако лучше использовать объекты, желательно со свойствами name и message. Встроенный в JavaScript конструктор Error() предоставляет удобный способ создания объекта ошибки. Давайте посмотрим на некоторые примеры:
throw 123;
throw "Missing values!";
throw true;
throw { name: "InvalidParameter", message: "Parameter is not a number!" };
throw new Error("Something went wrong!");
Если вы используете встроенные в JavaScript функции конструктора ошибок (например, Error(), TypeError() и т. д.) для создания объектов ошибок, тогда свойство name совпадает с именем конструктора, а message равно аргументу функции конструктора.
Теперь мы собираемся создать функцию squareRoot(), чтобы найти квадратный корень числа. Это можно сделать просто с помощью встроенной в JavaScript функции Math.sqrt(), но проблема здесь в том, что она возвращает NaN для отрицательных чисел, не давая никаких подсказок о том, что пошло не так.
Мы собираемся исправить эту проблему, показывая пользователю ошибку, если указано отрицательное число.
function squareRoot(number) {
// Выдает ошибку, если число отрицательное
if(number < 0) {
throw new Error("Sorry, can't calculate square root of a negative number.");
} else {
return Math.sqrt(number);
}
}
try {
squareRoot(16);
squareRoot(625);
squareRoot(-9);
squareRoot(100);
// Если выдается ошибка, следующая строка не будет выполнена
alert("All calculations are performed successfully.");
} catch(e) {
// Обработка ошибки
alert(e.message);
}
Теоретически можно вычислить квадратный корень из отрицательного числа, используя мнимое число i, где i2 = -1. Следовательно, квадратный корень из -4 равен 2i, квадратный корень из -9 равен 3i и так далее. Но мнимые числа не поддерживаются в JavaScript.
Типы ошибок
Объект Error является базовым типом всех ошибок и имеет два основных свойства: name, указывающее тип ошибки и свойство message, которое содержит сообщение, описывающее ошибку более подробно. Любая выданная ошибка будет экземпляром объекта Error.
Существует несколько различных типов ошибок, которые могут возникнуть во время выполнения программы JavaScript, например RangeError, ReferenceError, SyntaxError, TypeError, и URIError.
В следующем разделе описывается каждый из этих типов ошибок более подробно:
RangeError
RangeError генерируется, когда вы используете число, выходящее за пределы допустимых значений. Например, создание массива с отрицательной длиной вызовет RangeError.
var num = 12.735;
num.toFixed(200); // выдает ошибку диапазона (допустимый диапазон от 0 до 100)
var array = new Array(-1); // выдает ошибку диапазона
ReferenceError
Ошибка ReferenceError обычно выдается, когда вы пытаетесь сослаться на переменную или объект, которые не существуют, или получить к ним доступ. В следующем примере показано, как происходит ошибка ReferenceError.
var firstName = "Harry";
console.log(firstname); // выдает ошибку ссылки (имена переменных чувствительны к регистру)
undefinedObj.getValues(); // выдает ошибку ссылки
nonexistentArray.length; // выдает ошибку ссылки
SyntaxError
SyntaxError генерируется, если в вашем коде JavaScript есть какие-либо синтаксические проблемы. Например, если закрывающая скобка отсутствует, циклы не структурированы должным образом и т. д.
var array = ["a", "b", "c"];
document.write(array.slice(2); // выдает синтаксическую ошибку (отсутствует скобка)
alert("Hello World!'); // выдает синтаксическую ошибку (несоответствие кавычек)
TypeError
Ошибка TypeError возникает, когда значение не относится к ожидаемому типу. Например, вызов метода строки для числа, вызов метода массива для строки и т. д.
var num = 123;
num.toLowerCase(); /* выдает ошибку (поскольку toLowerCase() является строковым методом, число не может быть преобразовано в нижний регистр) */
var greet = "Hello World!"
greet.join() // выдает ошибку (так как join() является методом массива)
URIError
URIError генерируется, когда вы указали недопустимый URI (расшифровывается как Uniform Resource Identifier) для функций, связанных с URI, таких как encodeURI() или decodeURI(), как показано здесь:
var a = "%E6%A2%B";
decodeURI(a); // выдает ошибку URI
var b = "uD800";
encodeURI(b); // выдает ошибку URI
Существует еще один тип ошибки EvalError, который генерируется при возникновении ошибки во время выполнения кода с помощью функции eval(). Хотя эта ошибка больше не генерируется JavaScript, этот объект все еще остается для обратной совместимости.
Конкретный тип ошибки также может быть выдан вручную с использованием соответствующего конструктора и оператора throw. Например, чтобы сгенерировать ошибку TypeError, вы можете использовать конструктор TypeError(), например:
var num = prompt("Please enter a number");
try {
if(num != "" && num !== null && isFinite(+num)) {
alert(Math.exp(num));
} else {
throw new TypeError("You have not entered a number.");
}
} catch(e) {
alert(e.name);
alert(e.message);
alert(e.stack); // нестандартное свойство
}
Объект Error также поддерживает некоторые нестандартные свойства. Одним из наиболее широко используемых таких свойств является: stack trace, который возвращает трассировку стека для этой ошибки. Вы можете использовать его в целях отладки, но не используйте его на рабочих сайтах.
Типы ошибок
Последнее обновление: 30.08.2021

В блоке catch мы можем получить информацию об ошибке, которая представляет объект. Все ошибки, которые генерируются интерретатором JavaScript,
предоставляют объект типа Error, который имеет ряд свойств:
-
message: сообщение об ошибке
-
name: тип ошибки
Стоит отметить, что отдельные браузеры поддерживают еще ряд свойств, но их поведение в зависимости от браузера может отличаться:
-
fileName: название файла с кодом JavaScript, где произошла ошибка
-
lineNumber: строка в файле, где произошла ошибка
-
columnNumber: столбец в строке, где произошла ошибка
-
stack: стек ошибки
Получим данные ошибки, например, при вызове несуществующей функции:
try{
callSomeFunc();
}
catch(error){
console.log("Тип ошибки:", error.name);
console.log("Ошибка:", error.message);
}
Консольный вывод:
Тип ошибки: ReferenceError Ошибка: callSomeFunc is not defined
Типы ошибок
Выше мы рассмотрели, что генерируемая интерпретатором ошибка представляет тип Error, однако при вызове несуществующей функции
генерируется ошибка типа ReferenceError. Дело в том, что тип Error представляет общий тип ошибок. В то же время есть конкретные типы ошибок для определенных ситуаций:
-
EvalError: представляет ошибку, которая генерируется при выполнении глобальной функции
eval() -
RangeError: ошибка генерируется, если параметр или переменная, представляют число, которое находится вне некотоого допустимого диапазона
-
ReferenceError: ошибка генерируется при обращении к несуществующей ссылке
-
SyntaxError: представляет ошибку синтаксиса
-
TypeError: ошибка генерируется, если значение переменной или параметра представляют некорректный тип или пр попытке изменить значение, которое нельзя изменять
-
URIError: ошибка генерируется при передаче функциям
encodeURI()иdecodeURI()некорректных значений -
AggregateError: предоставляет ошибку, которая объединяет несколько возникших ошибок
Например, при попытке присвоить константе второй раз значение, генерируется ошибка 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);
}
Ошибки и исключения
В любой, особенно большой, программе могут возникать ошибки, приводящие к ее неработоспособности или к тому, что программа делает не то, что должна. Причин возникновения ошибок много.
Программист может сделать ошибку в употреблении самого языка программирования. Другими словами, выразиться так, как выражаться не положено. Например, начать имя переменной с цифры или забыть поставить двоеточие в заголовке сложной инструкции. Подобные ошибки называют синтаксическими, они нарушают синтаксис и пунктуацию языка. Интерпретатор Питона, встретив ошибочное выражение, не знает как его интерпретировать. Поэтому останавливает выполнение программы и выводит соответствующее сообщение, указав на место возникновения ошибки:
>>> 1a = 10 File "<stdin>", line 1 1a = 10 ^ SyntaxError: invalid syntax
В терминологии языка Python здесь возникло исключение, принадлежащее классу SyntaxError. Согласно документации Python синтаксические ошибки все-таки принято относить к ошибкам, а все остальные – к исключениям. В некоторых языках программирования не используется слово «исключение», а ошибки делят на синтаксические и семантические. Нарушение семантики обычно означает, что, хотя выражения написаны верно с точки зрения синтаксиса языка, программа не работает так, как от нее ожидалось. Для сравнения. Вы можете грамотным русским языком сказать несколько предложений, но по смыслу это будет белиберда, или вас поймут не так, как хотелось бы.
В Python не говорят о семантических ошибках, говорят об исключениях. Их множество. В этом уроке мы рассмотрим некоторые из них, в последующих встретимся с еще несколькими.
Если вы попытаетесь обратиться к переменной, которой не было присвоено значение, что в случае Python означает, что переменная вообще не была объявлена, она не существует, то возникнет исключение NameError.
>>> a = 0 >>> print(a + b) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'b' is not defined
Последнюю строку сообщения можно перевести как «Ошибка имени: имя ‘b’ не определено».
Если исключение возникает при выполнении кода из файла, то вместо «line 1» будет указана строка, в которой оно возникло, например, «line 24». Вместо «<stdin>» будет указано имя файла, например, «test.py». В данном же случае stdin обозначает стандартный поток ввода. По-умолчанию это поток ввода с клавиатуры. Строка 1 – потому что в интерактивном режиме каждое выражение интерпретируется отдельно, как обособленная программка. Если написать выражение, состоящее из нескольких строк, то линия возникновения ошибки может быть другой:
>>> a = 0 >>> if a == 0: ... print(a) ... print(a + b) ... 0 Traceback (most recent call last): File "<stdin>", line 3, in <module> NameError: name 'b' is not defined
Следующие два исключения, о которых следует упомянуть, и с которыми вы уже могли встретиться в предыдущих уроках, это ValueError и TypeError – ошибка значения и ошибка типа.
>>> int("Hi")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int()
with base 10: 'Hi'
>>> 8 + "3"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s)
for +: 'int' and 'str'
В примере строку «Hi» нельзя преобразовать к целому числу. Возникает исключение ValueError, потому что функция int() не может преобразовать такое значение.
Число 8 и строка «3» принадлежат разным типам, операнд сложения между которыми не поддерживается. При попытке их сложить возникает исключение TypeError.
Деление на ноль вызывает исключение ZeroDivisionError:
>>> 1/0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero
Обработка исключений. Оператор try-except
Когда ошибки в программе возникают в процессе написания кода или его тестирования, то код исправляется программистом так, чтобы ошибок не возникало. Однако нередко действия пользователя приводят к тому, что в программе возникает исключение. Например, программа ожидает ввод числа, но человек ввел букву. Попытка преобразовать ее к числу приведет к возбуждению исключения ValueError, и программа аварийно завершится.
На этот случай в языках программирования, в том числе Python, существует специальный оператор, позволяющий перехватывать возникающие исключения и обрабатывать их так, чтобы программа продолжала работать или корректно завершала свою работу.
В Питоне такой перехват выполняет оператор try-except. «Try» переводится как «попытаться», «except» – как исключение. Словами описать его работу можно так: «Попытаться сделать то-то и то-то, если при этом возникло исключение, то сделать вот это и это.» Его конструкция похожа на условный оператор с веткой else. Рассмотрим пример:
n = input("Введите целое число: ") try: n = int(n) print("Удачно") except: print("Что-то пошло не так")
Исключительная ситуация может возникнуть в третьей строчке кода, когда значение переменной n преобразуется к целому числу. Если это невозможно, то дальнейшее выполнение выражений в теле try прекращается. В данном случае выражение print("Удачно") выполнено не будет. При этом поток выполнения программы перейдет на ветку except и выполнит ее тело.
Если в теле try исключения не возникает, то тело ветки except не выполняется.
Вот пример вывода программы, когда пользователь вводит целое число:
Введите целое число: 100 Удачно
А здесь – когда вводит не то, что ожидалось:
Введите целое число: AA Что-то пошло не так
Есть одна проблема. Код выше обработает любое исключение. Однако в теле try могут возникать разные исключения, и у каждого из них должен быть свой обработчик. Поэтому более правильным является указание типа исключения после ключевого слова except.
try: n = input('Введите целое число: ') n = int(n) print("Все нормально. Вы ввели число", n) except ValueError: print("Вы ввели не целое число")
Теперь если сработает тело except мы точно знаем, из-за чего возникла ошибка. Но если в теле try возникнет еще какое-нибудь исключение, то оно не будет обработано. Для него надо написать отдельную ветку except. Рассмотрим программу:
try: a = float(input("Введите делимое: ")) b = float(input("Введите делитель: ")) c = a / b print("Частное: %.2f" % c) except ValueError: print("Нельзя вводить строки") except ZeroDivisionError: print("Нельзя делить на ноль")
При ее выполнении исключения могут возникнуть в трех строчках кода: где происходит преобразование введенных значений к вещественным числам и в месте, где происходит деление. В первом случае может возникнуть ValueError, во втором – ZeroDivisionError. Каждый тип исключения обрабатывается своей веткой except.
Несколько исключений можно сгруппировать в одну ветку и обработать совместно:
try: a = float(input("Введите делимое: ")) b = float(input("Введите делитель: ")) c = a / b print("Частное: %.2f" % c) except (ValueError, ZeroDivisionError): print("Нельзя вводить строки") print("или делить на ноль")
У оператора обработки исключений, кроме except, могут быть еще ветки finally и else (не обязательно обе сразу). Тело finally выполняется всегда, независимо от того, выполнялись ли блоки except в ответ на возникшие исключения или нет. Тело else сработает, если исключений в try не было, то есть не было переходов на блоки except.
try: n = input('Введите целое число: ') n = int(n) except ValueError: print("Неверный ввод") else: # когда в блоке try не возникло исключения print("Все нормально. Вы ввели число", n) finally: # выполняется в любом случае print("Конец программы")
Примечание. В данном коде используются комментарии. В языке Python перед ними ставится знак решетки #. Комментарии в программном коде пишутся исключительно для человека и игнорируются интерпретатором или компилятором.
Посмотрите, как выполняется программа в случае возникновения исключения и без этого:
pl@pl-desk:~$ python3 test.py Введите целое число: 4.3 Неверный ввод Конец программы pl@pl-desk:~$ python3 test.py Введите целое число: 4 Все нормально. Вы ввели число 4 Конец программы
В данном уроке изложены не все особенности обработки исключений. Так в более крупных программах, содержащих несколько уровней вложенности кода, функции, модули и классы, исключения могут обрабатываться не по месту их возникновения, а передаваться дальше по иерархии вызовов.
Также исключение может возникнуть в блоке except, else или finally, и тогда им нужен собственный обработчик. Модифицируем немного предыдущую программу и специально сгенерируем исключение в теле except:
try: n = input('Введите целое число: ') n = int(n) except ValueError: print("Неверный ввод") 3 / 0 except ZeroDivisionError: print("Деление на ноль") else: print("Все нормально. Вы ввели число", n) finally: print("Конец программы")
По началу может показаться, что все нормально. Исключение, генерируемое выражением 3 / 0 будет обработано веткой except ZeroDivisionError. Однако это не так. Эта ветка обрабатывает только исключения, возникающие в блоке try, к которому она сама относится. Вот вывод программы, если ввести не целое число:
Введите целое число: а Неверный ввод Конец программы Traceback (most recent call last): File "test.py", line 15, in <module> n = int(n) ValueError: invalid literal for int() with base 10: 'а' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "test.py", line 18, in <module> 3 / 0 ZeroDivisionError: division by zero
Мало того, что не было обработано деление на ноль, поскольку тело except ValueError неудачно завершилось, само исключение ValueError посчиталось необработанным. Решение проблемы может быть, например, таким:
… except ValueError: print("Неверный ввод") try: 3 / 0 except ZeroDivisionError: print("Деление на ноль") …
Здесь в тело except вложен свой внутренний обработчик исключений.
Практическая работа
Напишите программу, которая запрашивает ввод двух значений. Если хотя бы одно из них не является числом, то должна выполняться конкатенация, то есть соединение, строк. В остальных случаях введенные числа суммируются.
Примеры выполнения программы:
pl@pl-desk:~$ python3 test.py Первое значение: 4 Второе значение: 5 Результат: 9.0 pl@pl-desk:~$ python3 test.py Первое значение: a Второе значение: 9 Результат: a9
Примеры решения и дополнительные уроки в pdf-версии и android-приложении курса
В этом руководстве вы узнаете о типах ошибок в jаvascript.
Когда вы работаете на языке программирования jаvascript и если вы пишете что-то не так в скрипте, значит, вы, должно быть, видели, что во время работы в нем возникают какие-то ошибки. Для этого есть причина.
Во время написания скрипта вы получаете ошибку из-за неправильного написания синтаксиса или неправильного написания какой-то логики. Или он выполняет сценарий и возникает ошибка.
В jаvascript тоже есть похожие ошибки. И каждая ошибка возникает по разной причине.
Типы ошибок jаvascript
В jаvascript есть шесть типов ошибок, которые могут возникнуть во время выполнения скрипта:
- EvalError
- RangeError
- ReferenceError
- SyntaxError
- TypeError
- URIError
EvalError
jаvascript вызывает ошибку EvalError, если вы неправильно используете функцию eval(). Смотрите пример:
let e = new eval();
Ошибка:
TypeError: eval is not a constructor
Однако в этой ситуации веб-браузеры часто выдают ошибку TypeError вместо EvalError.
RangeError
Ошибка RangeError возникает, когда число не входит в диапазон. См. следующий пример:
try {
let list = Array(Number.MAX_VALUE);
} catch (error) {
console.log(error.name); // "RangeError"
console.log(error.message); // "Invalid array length"
}
Ошибка:
RangeError
Invalid array length
Внутри блока try возникает ошибка RangeError, потому что длина массива (Array) здесь не определена.
ReferenceError
Ошибка ReferenceError возникает, когда вы ссылаетесь на несуществующую переменную, функцию или объект. См. следующий пример:
try {
var a = a + c;
} catch (error) {
console.log(error.name); // "ReferenceError"
console.log(error.message); // "c is not defined"
}
Ошибка:
ReferenceError
c is not defined
В этом примере переменная «c» не существует, поэтому она вызывает ошибку ReferenceError.
SyntaxError
Ошибка SyntaxError возникает в строке, которую вы передаете функции eval(). См. следующий пример:
try {
eval('a x b');
} catch (error) {
console.log(error.name); // "SyntaxError"
console.log(error.message); // "Unexpected identifier"
}
Ошибка:
SyntaxError
Unexpected identifier
Вне функции eval() jаvascript прекращает выполнение кода всякий раз, когда обнаруживает SyntaxError.
TypeError
Ошибка TypeError возникает, если переменная имеет неожиданный тип или доступ к несуществующему методу.
try {
let x = new "String";
} catch(error) {
console.log(error.name); // "TypeError"
console.log(error.message); // "String" is not a constructor"
}
Ошибка:
TypeError
"String" is not a constructor
В этом примере мы попытались создать новый экземпляр литеральной строки (let), которая вызвала ошибку TypeError.
let db = {
host: 'localhost',
port: 3306,
user: 'root',
password: 'secret'
};
try {
db.connect();
} catch (error) {
console.log(error.name); // "TypeError"
console.log(error.message); // "db.connect is not a function"
}
В этом примере мы попытались получить доступ к методу connect() объекта db, которого не существует, поэтому произошла ошибка TypeError.
URIError
Ошибка URIError возникает при использовании encodeURI() или decodeURI() с искаженным URI. См. следующий пример:
console.log(encodeURI('uDFFF'));
Throwing errors
Чтобы выдать ошибку, вы можете использовать js оператор throw. См. следующий пример:
throw 'ABC';
throw 123;
Когда jаvascript достигает оператора throw, он немедленно останавливает выполнение скрипта. В этом случае, чтобы продолжить выполнение скрипта, вам нужно использовать оператор try … catch, чтобы перехватить выброшенное значение. См. следующий пример:
try {
throw 123;
} catch (error) {
console.log(error); // 123
}
console.log('continue!'); // "continue!"
Вы также можете использовать typeError, упомянутый ранее, как выдаваемую ошибку. См. следующий пример:
function add(a, b) {
if (typeof a !== 'number') {
throw TypeError('The first argument must be a number');
}
if (typeof b !== 'number') {
throw TypeError('The second argument must be a number');
}
return a + b;
}
add('string', 1);
Ошибка:
TypeError: The first argument must be a number
Пользовательская ошибка
Вы можете создать настраиваемую ошибку, которая возникает из-за встроенной ошибки jаvascript.
function InvalidCallError(message) {
this.name = 'InvalidCallError';
this.message = message;
}
InvalidCallError.prototype = Object.create(Error.prototype);
InvalidCallError.prototype.constructor = Error;
Затем вы можете выдать настраиваемую ошибку, как показано в этом примере:
throw new InvalidCallError('Invalid function call');
Ошибка:
"Uncaught InvalidCallError: Invalid function call"
I ‘ve inspected different behavior for undefined/undeclared variables in javascript .For example :
var obj = {};
console.log(x);//Error
console.debug(obj.x) ;//undefined
My question is though c and obj.x both are not declared or defined then why I’m getting diff behavior?
Am I missing something?
How should I track which variable is already exist or not?
asked Jul 20, 2012 at 6:37
You can’t reference an undeclared variable without it being an error, unless you are assigning it in non-strict mode then it becomes an implicit global. Still error in strict mode though.
Trying to access object properties is not the same as trying to access variables, though you can access global variables from window:
x; //referenceerror
window.x; //undefined, no reference error
You need to use window.x vs x in this situation for example:
var x = 5;
(function(){
var x = 3;
x === 3; //We cannot access the 5
window.x === 5 //Only window.x will do it here
})()
answered Jul 20, 2012 at 6:47
EsailijaEsailija
137k23 gold badges268 silver badges322 bronze badges
2
This is expected behavior in javascript. If you are accessing an undeclared variable (x), an error occurs because engine doesn’t know what you are trying to access.
On the other hand, objects have some sort of a dual nature. It acts as both an object and an array, and javascript allows you to try to access member of an array even if member under given key doesn’t exist. If there is no key under specified value, you will get back undefined.
I.e. following two lines are equivalent
console.log(obj.x);
and
console.log(obj["x"]);
You would only get error if you try to access member of non existing variable. E.g.
console.log(obj.x.x);
answered Jul 20, 2012 at 6:43
If you try to access an undefined variable, you will get an error, which is generally a good thing since it allows you to find bugs more easily.
If you want to find out if a variable is defined or not, you can check its type like this:
console.info(typeof x === "undefined" ? "<undefined!>" : x);
In the case of obj.x, x is a property not a variable and you can always look up a property because of the dynamic nature of JavaScript objects.
answered Jul 20, 2012 at 6:46
laurentlaurent
86.6k75 gold badges283 silver badges420 bronze badges








