有至少兩個不同和有用的策略實現類類型的代碼結構。一個是原型的,另一個是工廠式的繼承。
原型繼承
JavaScript的原型繼承是經典的和有效的。
// A viewable device.
function Device() {
var _element = null,
_type = 'div';
// Get or set the element type.
this.type = function type(type_) {
if (!arguments.length)
return _type;
_type = type_;
return this;
};
// Lazy creation of the element, or set it explicitly.
this.element = function element(element_) {
if (!arguments.length)
return _element || (_element = $('<' + _type + '>').get(0));
_element = element_;
return this;
};
// Allow constructor chaining on subclasses.
return this;
}
Device.prototype = Object.create(null);
Device.prototype.constructor = Device;
// Get/set. Hide or show this device.
Device.prototype.visible = function visible(show) {
if (!arguments.length)
return $(this.element()).css('display') !== 'none';
$(this.element()).css('display', show ? '' : 'none');
return this;
};
// Add or remove a css class, or check for its presence.
Device.prototype.classed = function classed(css_class, classed_) {
if(arguments.length === 1)
return $(this.element()).hasClass(css_class);
if (classed_)
$(this.element()).addClass(css_class);
else
$(this.element()).removeClass(css_class);
return this;
};
雖然Device
是一個基類,它可以被實例化,並且被配置如下:
// Create a list item device.
var ul = new Device()
.type('ul')
.classed('list-items', true)
.visible(false);
// Check for the class.
ul.classed('list-items'); // => true
// Is the device visible?
ul.visible() // => false
// Show the device.
ul.visible(true);
ul.visible(); // => true
爲了使list-items
設備的子類:
function ListItems() {
Device.call(this)
.classed('list-items', true)
.visible(false);
return this;
}
ListItems.prototype = Object.create(Device.prototype);
ListItems.prototype.constructor = ListItems;
ListItems.prototype.addItem = function addItem(content, css_class) {
$(this.element()).append($('<li>')
.addClass(css_class || 'list-item')
.html(content));
return this;
};
來實例化亞類:
var ul = new ListItems()
.addItem('Item 1')
.addItem('Item 2')
.addItem('Item 3')
.visible(true);
ul.element();
/*
<ul class="list-items">
<li class="list-item">Item 1</li>
<li class="list-item">Item 2</li>
<li class="list-item">Item 3</li>
</ul>
*/
廠繼承
廠繼承優雅,並消除了對new
關鍵字的需求,如果它是麻煩。
function device() {
var self = {},
_type = 'div',
_element = null;
self.type = function type(type_) {
if (!arguments.length)
return _type;
_type = type_;
return this;
};
self.element = function element(element_) {
if (!arguments.length)
return _element || (_element = $('<' + _type + '>').get(0));
_element = element_;
return this;
};
self.visible = function visible(show) {
if (!arguments.length)
return $(this.element()).css('display') !== 'none';
$(this.element()).css('display', show ? '' : 'none');
return this;
};
self.classed = function classed(css_class, classed_) {
if(arguments.length === 1)
return $(this.element()).hasClass(css_class);
if (classed_)
$(this.element()).addClass(css_class);
else
$(this.element()).removeClass(css_class);
return this;
};
return self;
}
要實例設備:
var ul = device()
.type('ul')
.classed('list-items', true)
.visible(false);
從設備繼承:
function listItems() {
var _super = device()
.type('ul')
.classed('list-items', true)
.visible(false),
self = Object.create(_super);
self.addItem = function addItem(content, css_class) {
$(this.element()).append($('<li>')
.addClass(css_class || 'list-item')
.html(content);
return this;
};
return self;
}
實例化時listItems:
var ul = listItems()
.addItem('Item 1')
.addItem('Item 2')
.addItem('Item 3')
.visible(true);
ul.element();
/*
<ul class="list-items">
<li class="list-item">Item 1</li>
<li class="list-item">Item 2</li>
<li class="list-item">Item 3</li>
</ul>
*/
使用哪種模式在很大程度上是一個事的偏好,雖然親totypal繼承類在調試器中具有不同的身份,因此可能更適合調試和分析情況。
原型繼承與instanceof
一起工作,所以這是另一個考慮因素。一個instanceOf
類型的機制可以添加到工廠繼承的一些努力。
instanceof和多態性尚不重要。我們只是想在這個階段重用通用代碼:) –