javascript - 在哪里/何时设置函数原型(prototype)?

标签 javascript prototype

我是 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 动态特性的概念是 MixinsAugmentation,它们有时比原型(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/

相关文章:

javascript - 获取CSS类属性数据绑定(bind)以附加而不是替换

javascript - magento bundle.js 错误

javascript - 如何从 Float32Array 创建矢量原型(prototype)?

javascript - 在回调中调用函数会在 Angular 中引发错误

javascript - 优先级 : Logical or vs. 三元运算符

javascript - 需要删除一个 P 类(无法在代码中删除它)

javascript - 如何处理与 jQuery 不冲突的对象类

javascript - 使用私有(private)/ protected /公共(public)字段和方法扩展类

JavaScript Object.prototype 按值

javascript - getEventsForDay() 日期选择器返回值的格式问题