Создание объекта JavaScript — сложная тема. В языке есть множество стилей для создания объектов, и новички, и ветераны могут чувствовать себя перегруженными выбором и неуверенными, что им следует использовать. Но, несмотря на разнообразие и то, насколько разным может выглядеть синтаксис для каждого из них, они более похожи, чем вы, вероятно, думаете. В этой статье я собираюсь познакомить вас с различными стилями создания объектов и с тем, как каждый из них строится на других поэтапно.

Литералы объекта

Первая остановка в нашем туре — самый простой способ создания объектов, объектный литерал. JavaScript рекламирует, что объекты могут быть созданы «ex nilo», из ничего — без класса, без шаблона, без прототипа — просто пуф, объект с методами и данными.

var o = { x: 42, y: 3.14, f: function() {}, g: function() {} };

Но есть недостаток. Если нам нужно создать объект того же типа в других местах, мы закончим тем, что скопируем и вставим методы объекта, данные и инициализацию. Нам нужен способ создать не один объект, а семейство объектов.

Заводские функции

Следующая остановка в нашем туре — Фабрика функций. Это самый простой способ создать семейство объектов с одинаковой структурой, интерфейсом и реализацией. Вместо того, чтобы создавать литерал объекта напрямую, вместо этого мы возвращаем литерал объекта из функции. Таким образом, если нам нужно создать объект одного и того же типа несколько раз или в нескольких местах, нам нужно только вызвать функцию.

function thing() { return { x: 42, y: 3.14, f: function() {}, g: function() {} }; } var o = thing();

Но есть недостаток. Такой подход может вызвать раздувание памяти, поскольку каждый объект содержит свою уникальную копию каждой функции. В идеале мы хотим, чтобы каждый объект совместно использовал только одну копию своих функций.

Цепочки прототипов

JavaScript предоставляет нам встроенный механизм для обмена данными между объектами, называемый цепочкой прототипов. Когда мы обращаемся к свойству объекта, оно может выполнить этот запрос, делегировав его другому объекту. Мы можем использовать это и изменить нашу фабричную функцию так, чтобы каждый создаваемый ею объект содержал только данные, уникальные для этого конкретного объекта, и делегировать все остальные запросы свойств одному общему объекту.

var thingPrototype = { f: function() {}, g: function() {} }; function thing() { var o = Object.create(thingPrototype); o.x = 42; o.y = 3.14; return o; } var o = thing();

На самом деле это настолько распространенный шаблон, что язык имеет встроенную поддержку для него. Нам не нужно создавать собственный общий объект (объект-прототип). Вместо этого для нас автоматически создается объект-прототип вместе с каждой функцией, и мы можем поместить туда наши общие данные.

thing.prototype.f = function() {}; thing.prototype.g = function() {}; function thing() { var o = Object.create(thing.prototype); o.x = 42; o.y = 3.14; return o; } var o = thing();

Но есть недостаток. Это приведет к некоторому повторению. Первая и последняя строки функции «вещь» будут почти дословно повторяться в каждой такой функции делегирования прототипа фабрике.

Классы ES5

Первоначально опубликовано на www.laravelfeed.com.