Хотя функции конструктора являются концептуально полезным методом для определения классов в JavaScript , существует альтернативный способ создания объектов для новых. Этот механизм, определенный в 5-м издании ECMA Script, все еще находится на переднем крае и находится во внедрении во многих браузерах, но обещает полностью исключить классы (по крайней мере, мы больше не будем видеть статические классы), способствуя непосредственному созданию объектов из прототипа.
Основной функцией для манипулирования объектами таким способом является Object.create (), который служит для создания экземпляров. В новых версиях JavaScript есть другие функции, доступные для Object, которые позволяют вам манипулировать объектом после его создания, манипулировать областью его свойств и даже добавлять методы получения и установки, аналогичные магическим методам PHP.
преимущества
С Object.create (), прототип объекта может быть установлен напрямую ; таким образом, вы можете определить цепочку наследования, где каждый объект ссылается на родительский объект как прототип, не создавая конструкторы функций для использования в качестве классов или анонимные функции для имитации механизма.
Вы также можете установить дополнительные свойства при создании объектов, и эти свойства могут быть украшены метаданными, такими как перечислимые , доступные для записи и удаляемые ; метаданные предотвращают удаление или изменение свойства и сообщают браузеру, какие свойства должны быть перечислены с помощью for..in .
Недостатки
Этот бесклассовый подход к объектной ориентации может быть страшным, но именно так работает JavaScript. Оператор instanceof перестанет работать, поскольку созданные объекты являются экземплярами анонимного класса. Я думаю, что концепция класса в JavaScript может быть заменена в будущем фабричными методами, которые отвечают не только за вызов нового оператора (который теперь обернут в Object.create ()), но также и за решение, какие свойства и методы следует настроить. объект.
Этот метод пока недостаточно поддерживается, и резервные реализации, описанные в книге разработки JavaScript, управляемой тестами, не могут полностью эмулировать некоторые вещи, такие как метаданные свойств или перехватчики get / set.
Служба поддержки
Я сказал вам, что это был кровоточащий край! Согласно Mozilla , это версии браузеров, которые поддерживают Object.create () в полной форме и с его компаньонами:
- Internet Explorer 9
- Firefox 4
- Chrome 5
- Нет версии Opera.
- Safari 5
Товарищи
JavaScript 1.8.5 (как его называет Mozilla), псевдоним EcmaScript 5-е издание (как сказано в кросс-браузерной спецификации) — это не только Object.create (): в Object есть множество других методов, доступных для простоты управления. Это наиболее полезно, на мой взгляд, если вы хорошо разбираетесь в языках программирования на основе классов;
- Object.defineProperty (object, propertyName, descriptor) позволяет добавить свойство к объекту после создания.
- Object.seal (объект) не позволяет другому коду удалять или добавлять свойства: попытки сделать это будут игнорироваться (без появления ошибок). Доступные для записи значения свойств могут быть изменены.
- Object.freeze (object) — это то же самое, что Object.seal (), но также не позволяет даже изменять существующие свойства.
Давайте углубимся в некоторый код
Вот пример кода в форме тестового примера для jsTestDriver, который выполняет Object.create () и другие удобные функции, которые я цитировал ранее. Вы видите, что мы можем манипулировать объектами и их цепочками прототипов, не определяя ни одного класса, как в классических примерах наследования.
TestCase("Object.create() and other useful functions from ECMAScript 5th edition", { "test should create a new object (prototype is null)" : function() { var o = Object.create(null); assertObject(o); }, "test an invalid prototype throws a TypeError exception" : function() { try { Object.create(42); fail('No exception thrown.'); } catch(e) { assertInstanceOf(TypeError, e); } }, "test should create a new object with the given prototype" : function() { var proto = { property : 'value' }; var o = Object.create(proto); assertEquals('value', o.property); }, "test should allow setting properties" : function() { var o = Object.create(null, { property : { value : 42 // also Mozilla.org use always 42 in examples } }); assertEquals(42, o.property); }, "test should allow setting properties metadata" : function() { var o = Object.create(null, { property : { value : 42, writable : false } }); o.property = 43; // no error! JavaScript always surprise me assertEquals(42, o.property); }, "test it's not even an instance of Object" : function() { var o = Object.create(null); assertNotInstanceOf(Object, o); // the function constructor remains anonymous }, "test Object.defineProperty() lets you define properties after construction" : function() { o = Object.create(null); Object.defineProperty(o, 'property', { value : 42 }); assertEquals(42, o.property); }, "test Object.freeze() is similar to Object.seal(), but does not allow modification" : function() { o = Object.create(null, { property : { value : 42 } }); Object.freeze(o); o.property = 43; assertEquals(42, o.property); delete o.property; assertEquals(42, o.property); }, });