#javascript #oop #inheritance #design-patterns
#javascript #ооп #наследование #шаблоны проектирования
Вопрос:
Я работаю с профессиональным JavaScript для веб-разработчиков, и у меня есть вопрос, касающийся создания объектов и наследования. В книге шаблон динамического прототипа обсуждается как хороший способ создания комбинации Конструктор / шаблон прототипа, сохраняя конструктор и прототип инкапсулированными в определение объекта. Вот так:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if (typeof this.sayName != "function") {
Person.prototype.sayName = function () {
return this.name;
};
}
}
Из всех шаблонов создания объектов, обсуждаемых в книге, мне показалось, что этот выглядит лучше всего. Затем, обсуждая наследование, в книге говорится, что наследование паразитных комбинаций считается оптимальной парадигмой наследования. Следующим образом:
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
SuperType.prototype.sayName = function() {
return this.name;
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
return this.age;
}
Как вы можете видеть, этот код использует комбинацию Конструктор / шаблон прототипа для создания объектов, где прототипы объявляются вне процесса создания исходного объекта. Мой вопрос в том, есть ли какие-либо проблемы с объединением шаблона динамического прототипа с наследованием паразитной комбинации, например:
function inheritPrototype(subType, superType){
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
if (typeof this.sayName != "function") {
SuperType.prototype.sayName = function() {
return this.name;
};
}
}
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
if (typeof this.sayAge != "function") {
SubType.prototype.sayAge = function() {
return this.age;
};
}
}
inheritPrototype(SubType, SuperType);
Я протестировал это в здесь jsfiddle, и, похоже, все работает нормально, я просто хотел убедиться, что я не упустил чего-то, что позже вызовет проблемы при использовании этого шаблона / наследования.
Кроме того, насколько я знаю, эта книга немного старше, существуют ли новые стандарты для создания объектов и наследования?
Комментарии:
1.
inheritPrototype
необходимо использоватьObject.create
неObject
2. Я должен сказать, что «шаблон динамического прототипа» выглядит довольно уродливо на мой взгляд… Также методы прототипа должны быть статическими, а не динамическими, поэтому можно утверждать, что создавать их в конструкторе (даже если только динамически) — плохая практика. Если вы ищете синтаксическую инкапсуляцию, лучше используйте IIFE вокруг конструктора наследование прототип или просто используйте классы ES6.
Ответ №1:
Оба подхода кажутся нарушенными.
Данные свойства прототипа объекта должны быть доступны, даже если функция конструктора еще не была вызвана. С другой стороны, похоже, что это нарушает принцип единой ответственности, потому что конструктор отвечает за определение прототипа, в то время как он должен просто инициализировать создаваемый объект.
Только один вопрос: как бы вы наследуете данного объекта прототипа до базового объекта не построено?:
var B = Object.create(A.prototype);
Подождите! A.prototype
не будет содержать ожидаемых свойств, если только какой-то код не вызовет new A()
раньше!
// Ugly as hell!
new A();
var B = Object.create(A.prototype);
В заключение, не пытайтесь сокращать JavaScript: лучше изучить его и не пытаться обернуть наследование бесполезными / бессмысленными функциями.
На самом деле, стандарты ECMA-Script 6 и выше уже определили синтаксический сахар, чтобы сделать цепочку прототипов JavaScript похожей на классическое наследование:
class B extends A
{
}
…что абсолютно эквивалентно:
function B() {}
B.prototype = Object.create(A.prototype);