Паттерн «Конструктор»
В классических объектно-ориентированных языках программирования «конструктор» — это специальный метод, используемый для инициализации созданного объекта, как только для него выделили память. «Конструктор» объектов интересен нам поскольку в JavaScript почти все является объектом
«Конструкторы» объектов используются для создания определенных типов объектов – подготавливает объект к использованию и принятию аргументов, которые «конструктор» может использовать для определения значений свойств элементов и методов, когда объект впервые создается.
Создание объекта
Вот три основных способа создания новых объектов в JavaScript:
// Каждый из следующих вариантов создаст новый пустой объект :
var newObject = {};
// или
var newObject = Object.create( Object.prototype );
// или
var newObject = new Object();
Там, где «конструктор» объектов в последнем примере создает объект-обертку для определенного значения, или где не передается никакое значение, он создает пустой объект и возвращает его.
Есть четыре способа, в котором ключи и значения могут быть заданы объекту:
/// Совместимые подходы ECMAScript 3
// 1. Синтаксис с точкой
// Задаем свойства
newObject.someKey = "Hello World";
// Получаем свойства
var value = newObject.someKey;
// 2. Синтаксис квадратных скобок
// Задаем свойства
newObject["someKey"] = "Hello World";
// Получаем свойства
var value = newObject["someKey"];
// Совместимые подходы ECMAScript 5
// По ссылке доступно больше информации:
// http://kangax.github.com/es5-compat-table/
// 3. Объект.defineProperty
// Задаем свойства
Object.defineProperty( newObject, "someKey", {
value: "for more control of the property's behavior",
writable: true,
enumerable: true,
configurable: true
});
// Если вышенаписанное трудно читается, то можно записать немного короче
// следующим образом :
var defineProp = function ( obj, key, value ){
var config = {
value: value,
writable: true,
enumerable: true,
configurable: true
};
Object.defineProperty( obj, key, config );
};
// Для дальнейшего использования мы создаем новый пустой объект "person"
var person = Object.create( Object.prototype );
// Заполняем объект свойствами
defineProp( person, "car", "Delorean" );
defineProp( person, "dateOfBirth", "1981" );
defineProp( person, "hasBeard", false );
console.log(person);
// В результате имеем:
//Объект {car: "Delorean", dateOfBirth: "1981", hasBeard: false}
// 4. Объект.defineProperties
// Задаем свойства
Object.defineProperties( newObject, {
"someKey": {
value: "Hello World",
writable: true
},
"anotherKey": {
value: "Foo bar",
writable: false
}
});
// Получение свойств для 3. и 4. может быть сделано с использованием любого из
// вариантов в 1. и 2.
Как мы увидим немного позже в книге, эти методы можно использовать даже для наследования, следующим образом:
// Использование:
// Создаем водителя гоночного автомобиля, который наследуется от объекта person
var driver = Object.create( person );
// Задаем некоторые свойства для водителя
defineProp(driver, "topSpeed", "100mph");
// Получаем унаследованное свойство ( 1981 )
console.log( driver.dateOfBirth );
// Получаем свойство, которое мы задали( 100mph )
console.log( driver.topSpeed );
Основные «Конструкторы»
Как мы видели ранее, JavaScript не поддерживает концепцию классов, но он поддерживает специальные функции «конструктора», работающие с объектами. Вызывая функцию с помощью простого префикса «new» мы говорим JS , что это функция «конструктор», она инициализирует новый объект с определенными в ней членами.
Внутри «конструктора» ключевое слово «this» ссылается на новый создающийся объект. Пересмотрим создание объекта, базовый конструктор может выглядеть следующим образом:
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
// Использование:
// Мы можем создавать новые экземпляры автомобиля
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
// затем откройте нашу консоль браузера, чтобы просмотреть
// результат метода ToString ( ) вызываемый
// на этих объектах
console.log( civic.toString() );
console.log( mondeo.toString() );
Выше представлена простая версия паттерна «конструктор», но он имеет некоторые проблемы. Одна из проблем – сложности с наследованием, а другая заключается в том то, что функции, такие как ToString ( ), переопределены для каждого из новых объектов, созданных с помощью конструктора автомобилей. Это не очень оптимально, так как функция в идеале должна быть разделена между всеми экземплярами типа автомобиль. К счастью, есть совместимые альтернаты построения объектов как ES3 так и ES5.
«Конструкторы» с прототипами
Функции, как и почти все объекты в JavaScript, содержат «прототип » объекта. Когда мы вызываем конструктор JavaScript для создания объекта, все свойства прототипа «конструктор» становятся доступными для нового объекта. Таким образом, могут быть созданы несколько объектов автомобиль, имеющих доступ к тому же прототипу. Мы можем изменить исходный пример следующим образом:
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
}
// Здесь следует отметить, что мы используем Объект.prototype.newMethod, а не
// Объект.prototype во избежания переопределения объекта прототипа
Car.prototype.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
// Использование:
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
console.log( civic.toString() );
console.log( mondeo.toString() );
Выше, один экземпляр ToString () теперь будет распределен между всеми объектами автомобиль.
Оригинал : addyosmani.com
Перевод: dev-tricks.ru