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