Книга: JavaScript. Подробное руководство, 6-е издание

6.2.3. Ошибки доступа к свойствам

6.2.3. Ошибки доступа к свойствам

Выражения обращения к свойствам не всегда возвращают или изменяют значение свойства. В этом разделе описываются ситуации, когда операции чтения или записи свойства терпят неудачу.

Попытка обращения к несуществующему свойству не считается ошибкой. Если свойство х не будет найдено среди собственных или унаследованных свойств объ¬екта о, выражение обращения к свойству о.х вернет значение undefined. Напомню, что наш объект book имеет свойство с именем «sub-title», но не имеет свойства «subtitle»:

book.subtitle; // => undefined: свойство отсутствует

Однако попытка обратиться к свойству несуществующего объекта считается ошибкой. Значения null и undefined не имеют свойств, и попытки обратиться к свойствам этих значений считаются ошибкой. Продолжим пример, приведенный выше:

// Возбудит исключение ТуреЕrror. Значение undefined не имеет свойства length
var len = book.subtitle.length;

Если нет уверенности, что book и book.subtitle являются объектами (или ведут себя подобно объектам), нельзя использовать выражение book.subtitle.length, так как оно может возбудить исключение. Ниже демонстрируются два способа защиты против исключений подобного рода:

// Более наглядный и прямолинейный способ
var len = undefined;
if (book) {
  if (book.subtitle) len = book.subtitle.length;
}
// Более краткая и характерная для JavaScript альтернатива получения длины
// значения свойства subtitle
var len = book && book.subtitle && book.subtitle.length;

Чтобы понять, почему второе выражение позволяет предотвратить появление исключений ТуреЕrror, можете вернуться к описанию короткой схемы вычислений, используемой оператором &&, в разделе 4.10.1. Разумеется, попытка установить значение свойства для значения null или undefined также вызывает исключение ТуреЕrror.

Попытки установить значение свойства для других значений не всегда оканчиваются успехом: некоторые свойства доступны только для чтения и не позволяют изменять их значения. Кроме того, некоторые объекты не позволяют добавлять в них новые свойства. Однако самое интересное, что подобные неудачи, как правило, не приводят к возбуждению исключения:

// Свойства prototype встроенных конструкторов доступны только для чтения.
Object.prototype = 0; // Присваивание не возбудит исключения;
                      // значение Object.prototype не изменится

Этот исторически сложившийся недостаток JavaScript исправлен в строгом режиме, определяемом стандартом ECMAScript 5. Все неудачные попытки изменить значение свойства в строгом режиме приводят к исключению ТуреЕrror.

Правила, позволяющие определить, когда попытка выполнить операцию присваивания завершится успехом, а когда неудачей, просты и понятны, но их сложно выразить в достаточно краткой форме. Попытка присвоить значение свойству р объекта о потерпит неудачу в следующих случаях:

• Объект о имеет собственное свойство р, доступное только для чтения: нельзя изменить значение свойства, доступного только для чтения. (Обратите, однако, внимание на метод defineProperty(), который представляет собой исключение, позволяющее изменять значения настраиваемых свойств, доступных только для чтения.)

• Объект о имеет унаследованное свойство р, доступное только для чтения: унаследованные свойства, доступные только для чтения, невозможно переопределить собственными свойствами с теми же именами.

• Объект о не имеет собственного свойства р; объект о не наследует свойство р с методами доступа и атрибут extensible (раздел 6.8.3) объекта о имеет значение false. Если свойство р отсутствует в объекте о и для него не определен метод записи, то операция присваивания попытается добавить свойство р в объект о. Но поскольку объект о не допускает возможность расширения, то попытка добавить в него новое свойство потерпит неудачу.

Оглавление книги


Генерация: 1.616. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз