// Более краткая и характерная для 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
. Если свойство
р
отсутствует в объекте
о
и для него не определен метод записи, то операция присваивания попытается добавить свойство
р
в объект
о
. Но поскольку объект
о
не допускает возможность расширения, то попытка добавить
в него новое свойство потерпит неудачу.
6.3. Удаление свойств
Оператор
delete
(раздел 4.13.3) удаляет свойство из объекта. Его единственный операнд должен быть выражением обращения к свойству. Может показаться удивительным, но оператор
delete
не оказывает влияния на значение свойства - он оперирует самим свойством:
delete book.author; // Теперь объект book не имеет свойства author,
delete book["main title"]; // Теперь он не имеет свойства "main title".
Оператор
delete
удаляет только собственные свойства и не удаляет унаследованные. (Чтобы удалить унаследованное свойство, необходимо удалять его в объекте-прототипе, в котором оно определено. Такая операция затронет все объекты, наследующие этот прототип.)
Выражение
delete
возвращает значение
true
в случае успешного удаления свойства или когда операция удаления не привела к изменению объекта (например, при попытке удалить несуществующее свойство). Выражение
delete
также возвращает
true
, когда этому оператору передается выражение, не являющееся выражением обращения к свойству:
о = {х:1}; //о имеет собственное свойство х и наследует toString
delete о.х; // Удалит х и вернет true
delete о.х; // Ничего не сделает (х не существует) и вернет true
delete о.toString; // Ничего не сделает (toString не собственное свойство) и вернет true
delete 1; // Бессмысленно, но вернет true
Оператор
delete
не удаляет ненастраиваемые свойства, атрибут
configurable
которых имеет значение
false
. (Однако он может удалять настраиваемые свойства нерасширяемых объектов.) Ненастраиваемыми являются свойства встроенных объектов, а также свойства глобального объекта, созданные с помощью инструкций объявления переменных и функций. Попытка удалить ненастраиваемое свойство в строгом режиме вызывает исключение
Type Error
. В нестрогом режиме (и в реализациях ECMAScript 3) в таких случаях оператор
delete
просто возвращает
false
:
delete Object.prototype; // Удаление невозможно - ненастраиваемое свойство
var х = 1; // Объявление глобальной переменной
delete this.x; // Это свойство нельзя удалить
function f {} // Объявление глобальной функции
delete this.f; // Это свойство также нельзя удалить
При удалении настраиваемых свойств глобального объекта в нестрогом режиме допускается опускать ссылку на глобальный объект и передавать оператору