Пример 6.4. Функция
<b>classoff()</b>
<b>function classof(o) {</b>
<b> if (о === null) return "Null";</b>
<b> if (o === undefined) return "Undefined";</b>
<b> return Object.prototype.toString.call(o).slice(8,-1);</b>
<b>}</b>
Этой функции classof() можно передать любое значение, допустимое в языке JavaScript. Числа, строки и логические значения действуют подобно объектам, когда относительно них вызывается метод
<b>toString()</b>
, а значения
<b>null</b>
и
<b>undefined</b>
обрабатываются особо. (В ECMAScript 5 особая обработка не требуется.) Объекты, созданные с помощью встроенных конструкторов, таких как
<b>Array</b>
и
<b>Date</b>
, имеют атрибут
<b>class</b>
, значение которого совпадает с именами их конструкторов. Объекты среды выполнения обычно также получают осмысленное значение атрибута
<b>class</b>
, однако это зависит от реализации. Объекты, созданные с помощью литералов или вызовом
<b>Object.сreate</b>
, получают атрибут
<b>class</b>
со значением «Object». Если вы определите свой конструктор, все объекты, созданные с его помощью, получат атрибут
<b>class</b>
со значением «Object»: нет никакого способа установить иное значение в атрибуте
<b>class</b>
для собственных классов объектов:
<b>classof(null) // => "Null"</b>
<b>classof(1) // => "Number"</b>
<b>classof("") // => "String"</b>
<b>classof(false) // => "Boolean"</b>
<b>classof({}) // => "Object"</b>
<b>classof([]) // => "Array"</b>
<b>classof(/./) // => "Regexp"</b>
<b>classof(new DateO) // => "Date"</b>
<b>classof(window) // => "Window" (объект клиентской среды выполнения)</b>
<b>function f() {}; // Определение собственного конструктора</b>
<b>classof(new f()); // => "Object"</b>
6.8.3. Атрибут extensible
Атрибут
<b>extensible</b>
объекта определяет, допускается ли добавлять в объект новые свойства. В ECMAScript 3 все встроенные и определяемые пользователем объекты неявно допускали возможность расширения, а расширяемость объектов среды выполнения определялась каждой конкретной реализацией. В ECMAScript 5 все встроенные и определяемые пользователем объекты являются расширяемыми, если они не были преобразованы в нерасширяемые объекты, а расширяемость объектов среды выполнения по-прежнему определяется каждой конкретной реализацией.
Стандарт ECMAScript 5 определяет функции для получения и изменения признака расширяемости объекта. Чтобы определить, допускается ли расширять объект, его следует передать методу
<b>Object.isExtensible().</b>
Чтобы сделать объект нерасширяемым, его нужно передать методу
<b>Object.preventExtensions()</b>
. Обратите внимание, что после того как объект будет сделан нерасширяемым, его нельзя снова сделать расширяемым. Отметьте также, что вызов
<b>preventExtensions()</b>
оказывает влияние только на расширяемость самого объекта. Если новые свойства добавить в прототип нерасширяемого объекта, нерасширяемый объект унаследует эти новые свойства.
Назначение атрибута
<b>extensible</b>
заключается в том, чтобы дать возможность «фиксировать» объекты в определенном состоянии, запретив внесение изменений. Атрибут объектов
<b>extensible</b>
часто используется совместно с атрибутами свойств
<b>configurable</b>
и
<b>writable</b>
, поэтому в ECMAScript 5 определяются функции, упрощающие одновременную установку этих атрибутов.
Метод
<b>Object.seal()</b>
действует подобно методу
<b>Object.preventExtensions()</b>
, но он не только делает объект нерасширяемым, но и делает все свойства этого объекта недоступными для настройки. То есть в объект нельзя будет добавить новые свойства, а существующие свойства нельзя будет удалить или настроить. Однако существующие свойства, доступные для записи, по-прежнему могут быть изменены.
После вызова
<b>Object.seal()</b>
объект нельзя будет вернуть в прежнее состояние. Чтобы определить, вызывался ли метод
<b>Object.seal()</b>
для объекта, можно вызвать метод
<b>Object.isSealed().</b>
Метод
<b>Object.freeze()</b>
обеспечивает еще более жесткую фиксацию объектов. Помимо того, что он делает объект нерасширяемым, а его свойства недоступными для настройки, он также делает все собственные свойства с данными доступными только для чтения. (Это не относится к свойствам объекта с методами доступа, обладающими методами записи; эти методы по-прежнему будут вызываться инструкциями присваивания.) Чтобы определить, вызывался ли метод
<b>Object.freeze()</b>
объекта, можно вызвать метод
<b>Object.isFrozen()</b>
.
Важно понимать, что
<b>Object.seal()</b>
и
<b>Object.freeze()</b>
воздействуют только на объект, который им передается: они не затрагивают прототип этого объекта. Если в программе потребуется полностью зафиксировать объект, вам, вероятно, потребуется зафиксировать также объекты в цепочке прототипов.
Все методы,
<b>Object.preventExtensions()</b>
,
<b>Object.seal()</b>
и
<b>Object.freeze()</b>
, возвращают переданный им объект, а это означает, что их можно использовать во вложенных вызовах: