Я создаю небольшую структуру JS для использования на своей работе, и я бы хотел использовать прототипные образцы наследования Дугласа Крокфорда. Я думаю, что я получаю общее представление о том, как работает объект-прототип, но неясно, как использовать этот шаблон за простейшим примером.
Я разберусь до такой степени, что я это понимаю.
(function () {
'use strict';
var Vehicles = {};
Vehicles.Vehicle = function () {
this.go = function () {
//go forwards
};
this.stop = function () {
//stop
};
};
Vehicles.Airplane = Object.create(Vehicles.Vehicle());
}());
Итак, теперь мои объекты Vehicle.Airplane могут идти() и останавливать(), но я хочу больше. Я хочу добавить к этому объекту методы takeOff() и land(). Я мог бы просто использовать уродливую нотацию:
Vehicles.Airplane.takeOff = function () {
//take off stuff
}
Но это кажется неправильным, особенно если я должен добавить много методов или свойств. Вопрос заданный здесь, похоже, очень похож на мой, но ответ не совсем верен для меня. Ответ предполагает, что перед использованием Object.create я должен построить литерал объекта и передать этот литерал объекта в метод create. Однако в приведенном примерном коде выглядит, что их новый объект вообще ничего не наследует.
Я надеюсь, что это синтаксис, похожий на:
Vehicles.Airplane = Object.create(Vehicles.Vehicle({
this.takeOff = function () {
//takeOff stuff
};
this.land = function () {
//land stuff
};
}));
Я знаю, что этот синтаксис будет сильно нарушен с Object.create прямо сейчас, потому что, конечно, я пропускаю Vehicle.Vehicle как функцию, а не литерал объекта. Это не важно. Мне интересно, каким образом я должен строить новые свойства в объект, который наследуется от другого, не указывая их по очереди за точечной нотацией после факта.
EDIT:
Берги, после некоторой мучительной мысли по этой теме, я думаю, что я действительно хочу пойти с тем, что вы описали как "Классический паттерн". Вот мой первый удар в нем (теперь с фактическими фрагментами кода, а не с фальсификацией гипотез - вы даже можете увидеть мои загроможденные заглушки):CS.Button = function (o) {
o = o || {};
function init(self) {
self.domNode = dce('a');
self.text = o.text || '';
self.displayType = 'inline-block';
self.disabled = o.disabled || false;
self.domNode.appendChild(ctn(self.text));
if (o.handler) {
self.addListener('click', function () {
o.handler(self);
});
}
}
this.setText = function (newText) {
if (this.domNode.firstChild) {
this.domNode.removeChild(this.domNode.firstChild);
}
this.domNode.appendChild(ctn(newText));
};
init(this);
};
CS.Button.prototype = Object.create(CS.Displayable.prototype, {
constructor: {value: CS.Button, configurable: true}
});
CS.Displayable = function (o) { // o = CS Object
o = o || {};
var f = Object.create(new CS.Element(o));
function init(self) {
if (!self.domAnchor) {
self.domAnchor = self.domNode;
}
if (self.renderTo) {
self.renderTo.appendChild(self.domAnchor);
}
}
//Public Methods
this.addClass = function (newClass) {
if (typeof newClass === 'string') {
this.domNode.className += ' ' + newClass;
}
};
this.addListener = function (event, func, capture) {
if (this.domNode.addEventListener) {
this.domNode.addEventListener(event, func, capture);
} else if (this.domNode.attachEvent) {
this.domNode.attachEvent('on' + event, func);
}
};
this.blur = function () {
this.domNode.blur();
};
this.disable = function () {
this.disabled = true;
};
this.enable = function () {
this.disabled = false;
};
this.focus = function () {
this.domNode.focus();
};
this.getHeight = function () {
return this.domNode.offsetHeight;
};
this.getWidth = function () {
return this.domNode.offsetWidth;
};
this.hide = function () {
this.domNode.style.display = 'none';
};
this.isDisabled = function () {
return this.disabled;
};
this.removeClass = function (classToRemove) {
var classArray = this.domNode.className.split(' ');
classArray.splice(classArray.indexOf(classToRemove), 1);
this.domNode.className = classArray.join(' ');
};
this.removeListener = function () {
//Remove DOM element listener
};
this.show = function () {
this.domNode.style.display = this.displayType;
};
init(this);
};
CS.Displayable.prototype = Object.create(CS.Element.prototype, {
constructor: {value: CS.Displayable, configurable: true}
});
Я должен быть предельно ясным и сказать, что он еще не совсем работает, но в основном я бы хотел, чтобы ваше мнение о том, действительно ли я на правильном пути. Вы упомянули "свойства и методы, специфичные для экземпляра" в комментарии в вашем примере. Означает ли это, что мой метод this.setText и другие ошибочно размещены и не будут доступны для потомков в цепочке прототипов?
Кроме того, при использовании кажется, что теперь имеет смысл порядок объявления (я не могу получить доступ к CS.Displayable.prototype, потому что (я думаю) CS.Button указан первым, а CS.Displayable - undefined at время, когда я пытаюсь ссылаться на него). Это что-то, что мне нужно, чтобы справиться и разобраться (поместить вещи в порядок родословной в коде, а не в алфавитном порядке OCD), или есть что-то, что я тоже вижу там?