Большинство реализаций JavaScript (за исключением веб-броузера IE) поддерживали синтаксис
<b>get</b>
и
<b>set</b>
в литералах объектов еще до принятия стандарта ECMAScript 5. Эти реализации поддерживают нестандартный, устаревший API для получения и назначения методов чтения и записи. Этот API состоит из четырех методов, доступных во всех объектах.
<b>__lookupGetter__()</b>
и
<b>__lookupSetter__()</b>
возвращают методы чтения и записи для указанного свойства. А методы
<b>__defineGetter__()</b>
и
<b>__defineSetter__()</b>
позволяют определить метод чтения или записи:
в первом аргументе они принимают имя свойства, а во втором - метод чтения или записи. Имена всех этих методов начинаются и оканчиваются двумя символами подчеркивания, чтобы показать, что они являются нестандартными методами. Эти нестандартные методы не описываются в справочном разделе.
6.8. Атрибуты объекта
Все объекты имеют атрибуты
<b>prototype</b>
,
<b>class</b>
и
<b>extensible</b>
. Все эти атрибуты описываются в подразделах ниже; в них также рассказывается, как получать и изменять значения атрибутов (если это возможно).
6.8.1. Атрибут prototype
Атрибут
<b>prototype</b>
объекта определяет объект, от которого наследуются свойства. (Дополнительные сведения о прототипах и наследовании прототипов приводятся в разделах 6.1.3 и 6.2.2.) Этот атрибут играет настолько важную роль, что обычно мы будем говорить о нем как о «прототипе объекта о», а не как об «атрибуте
<b>prototype</b>
объекта о». Кроме того, важно понимать, что когда в программном коде встречается ссылка
<b>prototype</b>
, она обозначает обычное свойство объекта, а не атрибут
<b>prototype</b>
.
Атрибут
<b>prototype</b>
устанавливается в момент создания объекта. В разделе 6.1.3 уже говорилось, что для объектов, созданных с помощью литералов, прототипом является
<b>Object.prototype</b>
. Прототипом объекта, созданного с помощью оператора
<b>new</b>
, является значение свойства
<b>prototype</b>
конструктора. А прототипом объекта, созданного с помощью
<b>Object.сreate(),</b>
становится первый аргумент этой функции (который может иметь значение
<b>null</b>
).
Стандартом ECMAScript 5 предусматривается возможность определить прототип любого объекта, если передать его методу
<b>Object.getPrototypeOf().</b>
В ECMAScript 3 отсутствует эквивалентная функция, но зачастую определить прототип объекта о можно с помощью выражения
<b>о.constructor.prototype</b>
. Объекты, созданные с помощью оператора
<b>new</b>
, обычно наследуют свойство
<b>constructor</b>
, ссылающееся на функцию-конструктор, использованную для создания объекта. И как уже говорилось выше, функции-конструкторы имеют свойство
<b>prototype</b>
, которое определяет прототип объектов, созданных с помощью этого конструктора. Подробнее об этом рассказывается в разделе 9.2, где также объясняется, почему этот метод определения прототипа объекта не является достаточно надежным. Обратите внимание, что объекты, созданные с помощью литералов объектов или
<b>Object.сгеate(),</b>
получают свойство
<b>constructor</b>
, ссылающееся на конструктор
<b>Object().</b>
Таким образом,
<b>constructor.prototype</b>
ссылается на истинный прототип для литералов объектов, но обычно это не так для объектов, созданных вызовом
<b>Object.create().</b>
Чтобы определить, является ли один объект прототипом (или звеном в цепочке прототипов) другого объекта, следует использовать метод
<b>isPrototypeOf().</b>
Чтобы узнать, является ли
<b>р</b>
прототипом
<b>о</b>
, нужно записать выражение
р.isPrototypeOf(о)
. Например:
<b>var р = {х:1}; // Определить объект-прототип.</b>
<b>var о = Object.сreate(p); // Создать объект с этим прототипом.</b>
<b>р.isPrototypeOf(o) // => true: о наследует р</b>
<b>Object.prototype.isPrototypeOf(р) // => true: р наследует Object.prototype</b>
Обратите внимание, что
<b>isPrototypeOf()</b>
по своему действию напоминает оператор
<b>instanceof</b>
(раздел 4.9.4).
В реализации JavaScript компании Mozilla (первоначально созданной в Netscape) значение атрибута
<b>prototype</b>
доступно через специальное свойство
<b>__proto__</b>
, которое можно использовать напрямую для определения и установки прототипа любого объекта. Использование свойства
<b>__proto__ </b>
ухудшает переносимость: оно отсутствует (и, вероятно, никогда не появится) в реализациях броузеров IE или Opera, хотя в настоящее время оно поддерживается броузерами Safari и Chrome. Версии Firefox, реализующие стандарт ECMAScript 5, все еще поддерживают свойство
<b>__proto__</b>
, но не позволяют изменять прототип нерасширяемых объектов.
6.8.2. Атрибут class
Атрибут
<b>class</b>
объекта - это строка, содержащая информацию о типе объекта. Ни в ECMAScript 3, ни в ECMAScript 5 не предусматривается возможность изменения этого атрибута и предоставляются лишь косвенные способы определения его значения. По умолчанию метод
<b>toString()</b>
(наследуемый от
<b>Object.prototype</b>
) возвращает строку вида:
<b>[object class]</b>
Поэтому, чтобы определить класс объекта, можно попробовать вызвать метод
<b>toString()</b>
этого объекта и извлечь из результата подстроку с восьмого по предпоследний символ. Вся хитрость состоит в том, что многие методы наследуют другие, более полезные реализации метода
<b>toString()</b>
, и чтобы вызвать нужную версию
<b>toString(),</b>
необходимо выполнить косвенный вызов с помощью метода
<b>Function.саll()</b>
(раздел 8.7.3). В примере 6.4 определяется функция, возвращающая класс любого объекта, переданного ей.