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

Пример 6.4. Функция

<b>classoff()</b>

<b>function classof(o) {</b>

<b>  if (о === null) return &quot;Null&quot;;</b>

<b>  if (o === undefined) return &quot;Undefined&quot;;</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)      // =&gt; &quot;Null&quot;</b>

<b>classof(1)         // =&gt; &quot;Number&quot;</b>

<b>classof(&quot;&quot;)        // =&gt; &quot;String&quot;</b>

<b>classof(false)     // =&gt; &quot;Boolean&quot;</b>

<b>classof({})        // =&gt; &quot;Object&quot;</b>

<b>classof([])        // =&gt; &quot;Array&quot;</b>

<b>classof(/./)       // =&gt; &quot;Regexp&quot;</b>

<b>classof(new DateO) // =&gt; &quot;Date&quot;</b>

<b>classof(window)    // =&gt; &quot;Window&quot; (объект клиентской среды выполнения)</b>

<b>function f() {};   // Определение собственного конструктора</b>

<b>classof(new f());  // =&gt; &quot;Object&quot;</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>
, возвращают переданный им объект, а это означает, что их можно использовать во вложенных вызовах: