Эффективные шаблоны создания экземпляров в JavaScript и способы их использования.

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

Эффективные шаблоны могут уменьшить объем кода, который мы пишем, объем кода в памяти и удобочитаемость вашего кода для других разработчиков.

Мы собираемся посмотреть, как можно создать некоторые из общепринятых шаблонов.

Функциональная реализация

Это включает в себя создание пустого объекта, присвоение его свойств и методов, а затем возврат объекта.

Это самая простая и, по мнению некоторых, самая легкая для чтения форма создания экземпляра.

Каждый раз, когда создается экземпляр Plant, код внутри этой функции дублируется. Это означает, что каждый экземпляр Plant имеет свою собственную копию, например, методов water и repot.

В нашем случае, когда у нас всего несколько копий, это не так уж важно, но не оптимально, когда у вас сотни или тысячи экземпляров.

Другая потенциальная проблема заключается в том, что нет общего происхождения, поскольку каждый экземпляр отличается, и если вы хотите что-то изменить, вам нужно будет делать это для каждого отдельного экземпляра.

// Functional
function Plant(name, size, flowerColor) => {
  var obj = {};
  obj.name = name;
  obj.size = size;
  obj.flowerColor = flowerColor;
  
  obj.water = function(){
    // Code to water plant
    console.log("Water the " + this.name)
  }
  
  obj.repot = function(){
    // Code to repot Plant
    console.log("Repotting")
  }
  
  return obj;
  
}
var daffodil = Plant("daffodil", "medium", "yellow")
console.log(daffodil.water()) // Water the daffodil

Функциональное совместное создание

Подобен функциональному вызову во многих отношениях, но также отличается во многих отношениях.

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

Проблемы возникают, если мне нужно изменить общие методы и свойства. После создания экземпляра переменная теряет связь с общими методами. Таким образом, никакие изменения не будут переданы экземплярам, ​​созданным до изменения.

// Functional Shared
function _extend(obj){
  var objects = arguments;
  Object.assign(obj, ...objects)
  return obj
}
function Plant(name, size, flowerColor) {
  var obj = {};
  obj.name = name;
  obj.size = size;
  obj.flowerColor = flowerColor;
  
  _extend(obj, plantMethods)
  
  return obj;
}
var plantMethods = {
  
  water: function(){
    // Code to water plant
    console.log("Water the " + this.name)
  },
  
  repot: function(){
    // Code to repot Plant
    console.log("Repot the plant")
  }
  
}

Прототипное воплощение

Прежде чем мы рассмотрим этот шаблон, мы должны сначала понять прототипную природу JS. JS, который был языком на основе прототипов, ведет себя иначе, чем классические языки на основе классов, такие как Java или PHP.

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

В ECMAScript 5 появился новый метод: Object.create(). Вызов этого метода создает новый объект. Но самое главное, что делает Object.create - это присоединяет методы и свойства к прототипу объекта, а не возвращает их внутри объекта. Каждый метод доступен для каждого созданного объекта без дублирования методов в памяти.

Этот метод позволяет нам напрямую установить __proto__ property способом, который представляет собой одно событие, что позволяет браузеру дополнительно оптимизировать объект. Он также позволяет создавать объекты без прототипа, используя Object.create(null).

function Plant(name, size, flowerColor) {
  var obj = Object.create(plantMethods)
  obj.name = name;
  obj.size = size;
  obj.flowerColor = flowerColor;
  
  return obj;
}
var plantMethods = {
 
  water: function(){
    // Code to water plant
    console.log("Water the " + this.name)
  },
  
  repot: function(){
    // Code to repot Plant
    console.log( "Repot the plant")
  }
  
}
var daffodil = Plant("daffodil", "medium", "yellow")
console.log(daffodil.water()) // Water the daffodil

Медленная инициализация объекта может быть черной дырой производительности при использовании второго аргумента, потому что каждое свойство объекта-дескриптора имеет свой собственный отдельный объект-дескриптор. При работе с сотнями тысяч объектных дескрипторов в форме объектов время запаздывания может стать серьезной проблемой .

Псевдоклассическая реализация

Псевдоклассическое создание экземпляров пытается преодолеть объем типизации, необходимый для создания объекта с использованием прототипного экземпляра. Подобно прототипу, псевдоклассическое создание экземпляров использует цепочку прототипов.

Но лучше всего то, что значительно сокращается объем кода, который мы обычно вносим, ​​потому что всю следующую работу JavaScript выполняет за нас под капотом.

  • Создает новый объект.
  • Привязывает ключевое слово this к этому новому объекту.
  • Устанавливает __proto__ нового объекта, или внутреннее свойство прототипа, в качестве прототипа строящей функции.
  • В конце функции, если не указан другой возврат, возвращается this (новый объект).
function Plant(name, size, flowerColor) {
  this.name = name
  this.size = size;
  this.flowerColor = flowerColor;
}
Plant.prototype.water = function(){
   // Code to water plant
   console.log("Water the " + this.name)
}
Plant.prototype.repot = function(){
   // Code to repot Plant
   console.log("Repot the plant")
}
var daffodil = new Plant("daffodil", "medium", "yellow")
console.log(daffodil.water()) // Water the daffodil

ES6 Псевдоклассическая реализация

ECMAScript 2015 представил новый набор ключевых слов, реализующих классы. Новые ключевые слова включают class, constructor, static, extends и super.

По сути, классы позволяют нам воспроизвести классический подход к созданию экземпляров. Однако, если бы мы заглянули под капот, мы бы увидели, что он по-прежнему работает так же. Он по-прежнему будет содержать внутреннее свойство прототипа и возвращать его как новый объект.

class Plant{
 constructor(size, flowerColor){
  this.size = size;
  this.flowerColor = flowerColor;
 }
 
 water(){
   // Code to water plant
    console.log("Water the " + this.name)
 }
 
 repot(){
   // Code to repot Plant
    console.log( "Repot the plant")
 }
}
var daffodil = new Plant("daffodil", "medium", "yellow")
console.log(daffodil.water()) // Water the daffodil

И вот оно. Надеюсь, вы нашли это полезным. Спасибо за чтение. Если вам понравилось и вы нашли это полезным, вы также можете насладиться некоторыми из идей, которые мы создали в !! nerdy. Новые дизайны выпускаются каждый месяц.