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 . Если свойство р отсутствует в объекте о и для него не определен метод записи, то операция присваивания попытается добавить свойство р в объект о . Но поскольку объект о не допускает возможность расширения, то попытка добавить в него новое свойство потерпит неудачу.
Оператор delete (раздел 4.13.3) удаляет свойство из объекта. Его единственный операнд должен быть выражением обращения к свойству. Может показаться удивительным, но оператор delete не оказывает влияния на значение свойства - он оперирует самим свойством:
delete book.author; // Теперь объект book не имеет свойства author,
delete book["main title"]; // Теперь он не имеет свойства "main title".
Оператор delete удаляет только собственные свойства и не удаляет унаследованные. (Чтобы удалить унаследованное свойство, необходимо удалять его в объекте-прототипе, в котором оно определено. Такая операция затронет все объекты, наследующие этот прототип.)
Читать дальше
Конец ознакомительного отрывка
Купить книгу