我是 JavaScript 原型(prototype)新手。
在示例中,原型(prototype)是根据主程序定义内嵌分配的,但这样做会影响启动顺序。
下面显示了我目前如何将原型(prototype)应用于一组单例。为了清楚起见,最好在后代类中分配原型(prototype),或者在更明显“绑定(bind)”到它的地方。 (请注意,面板在 Controller 内实例化以强制分离。)
还有其他位置/方法可以完成我忽略的任务吗?另外,我当前的方法是否违反了任何众所周知的风格?
var controller = new Controller();
function Controller() {
var panels = {
search: SearchPanel,
results: ResultsPanel,
details: DetailsPanel,
action: ActionPanel,
};
$.each(panels, function (i, v) {
// THE QUESTION REFERS TO THIS FOLLOWING STATEMENT:
v.prototype = new PanelCommon();
panels[i] = new v();
});
this.publish = function (site, message) {
$.each(panels, function (i, v) {
if (v[site]) v[site](message);
});
}
/*...*/
}
function PanelCommon() { /*...*/ }
function SearchPanel() { /*...*/ }
function ResultsPanel() { /*...*/ }
function DetailsPanel() { /*...*/ }
function ActionPanel() { /*...*/ }
最佳答案
另一个适合 JavaScript 动态特性的概念是 Mixins
或 Augmentation
,它们有时比原型(prototype)继承更自然。
mixin 是什么意思?
一个“mixin”,它接受一个对象,并注入(inject)更多的功能。基本上,我们的想法是我们将获取一个对象,并开始向它添加行为。
考虑以下 mixinPanelTo()
函数。它将是一个接受构造函数并向其原型(prototype)添加通用 render()
函数的函数。
var mixinPanelTo = (function() {
var render = function() {
// a render function that all panels share
console.log("rendering!")
}
// Augment
return function(cls) {
cls.prototype.render = render;
}
})();
现在我们有了这个,我们可以将该功能混合到我们想要的任何构造函数中:
var SearchPanel = function() {}
SearchPanel.prototype.search = function(query) {
/* search stuff */
this.render();
}
mixinPanelTo(SearchPanel)
那么,我们应该能够
var panel = new SearchPanel()
panel.search("foo"); // "rendering!" on the console
多个混入
与继承相比,mixins 的一个优点是对应用功能的更精细控制,以及从多个父级借用功能的能力
var mixinRender = function(cls) { /* inject render */ }
var mixinSearch = function(cls) { /* inject search */ }
var mixinInfiniteScroll = function(cls) { /* inject infinite scroll */ }
var customPanel = function() {}
mixinRender(customPanel);
mixinSearch(customPanel);
mixinInfiniteScroll(customPanel)
使用原型(prototype)继承很难实现这一点。除了尝试创建一个奇怪的类层次结构之外。
借阅功能
您还可以从目标类中获取 mixin 所需的功能/配置。例如,让我们以 mixinInfinitScroll
var mixinInfiniteScroll = function(cls, fetch) {
var page = 0;
cls.prototype.more = function() {
var data
// get more results
if(typeof fetch == "function")
data = fetch.call(this, ++page)
else
// assume a key in this
data = this[fetch](++page)
/* do work with data */
}
}
然后在混合此功能时,我们可以注入(inject)特定功能:
// by key
var Panel1 = function() { }
Panel1.prototype.fetch = function() { /* go get more results */ }
mixinInifiniteScroll(Panel1, "fetch")
// or even with a direct reference
var Panel1 = function() { }
Panel1.prototype.fetch = function() { /* go get more results */ }
mixinInifiniteScroll(Panel1, Panel1.prototype.fetch)
// or even an anonymous function
var Panel1 = function() { }
mixinInifiniteScroll(Panel1, function() { /* go get more results */ })
重写方法
您还可以重写 mixin 中的原型(prototype)方法,这使得它们非常强大
var augmentRender = function(cls, renderFn) {
var oldRender = cls.prototype[renderFn];
cls.prototype[renderFn] = function() {
/* prep */
oldRender.apply(this, arguments);
/* make some more changes */
}
}
然后我们可以说:
var Panel = function() { }
Panel.prototype.render = function() { /* my render */ }
augmentRender(Panel, "render")
无论如何,并不是说原型(prototype)继承有什么问题,但这可能会给您更多关于不同方法的想法,通过以不同的方式处理问题来解决问题。
关于javascript - 在哪里/何时设置函数原型(prototype)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20020989/