javascript - 特定对象实例的自定义函数 - 我有什么可能性?

标签 javascript jquery oop handlebars.js javascript-objects

所以我目前正在构建一个相当大的框架,用于许多网络项目。我很乐意针对以下场景获得一些建议或最佳实践。

我在网络应用程序中有不同的章节。一次只能看到一章。

函数createView()在第一次访问章节时被调用。它通过 Handlebars 模板创建 View ,插入 XML 文档中的所有副本(我们为每种语言都有一个 XML),并通过 start() 函数开始章节。每当再次访问章节时都会调用 start() 。它只是将 View 插入到 DOM 中并启用所有功能,如点击事件、其他模块(图库、 slider 等)等。

var Chapter = function(name) {
    this.name = name;
    this.createView();
};

Chapter.prototype.createView = function() {
    var self = this;
    
    // get handlebars template
    this.template = config.app.getTemplate('chapters/'+self.name).then(function(hbs) {
        
        // compile hbs template, insert data here - if there is any
        var html = hbs();
        
        // save jQuery collection of HTML as view
        self.view = $(html);
        
        // insert copy from XML doc
        self.view.find('[data-text]').each(function() {
            var theID = '#'+$(this).attr('data-text');
            var theText = config.xml.find(theID).text();
            $(this).html(theText);
        });
        
        // start the experience
        self.start();
        
    });
};

Chapter.prototype.start = function() {
    
    // stop active experience
    if(config.experiences.active) {
        config.experiences.active.stop();
    }
    
    // scroll to top
    $(window).scrollTop(0);
    
    // save this chapter as the active one
    config.experiences.active = this;
    
    // insert view into DOM
    this.view.appendTo($('main'));
    
    // enable functionality
    this.initModules();
    this.initNavigation();
    this.initLocking();
    
};

现在,Chapter 的每个实例都需要一些自定义函数,因为每个章节在许多项目中看起来都不同。但我不确定这是否是最好的方法:

initCustoms 中使用大量 if-else。

Chapter.prototype.start = function() {
    ...
    this.initCustoms();
};

Chapter.prototype.initCustoms = function() {
    if(this.name === 'Fire and Ice') {
        // do abc
    } else if(this.name === 'Second Sons') {
        // do xyz
    }
};

那么添加一堆 if-else 语句真的是正确的方法吗?看起来很……肮脏。 我还想:

为自定义章节创建一个对象并继承其原型(prototype)

var FireAndIce = function() {
    // do abc
}

FireAndIce.prototype = Chapter.prototype;
FireAndIce.prototype.constructor = Chapter;

Chapter.prototype.start = function() {
    ...
    this.initCustoms();
};

Chapter.prototype.initCustoms = function() {
    if(this.name === 'Fire and Ice') {
        // inherit functionality of FireAndIce. Can't post it here as I have not been able to do this properly.
    }
    ...
};

但这只会导致继承问题,更改其他实例或主 Chapter 原型(prototype)。我不想将 FireAndIce 的所有功能复制到实例,并且根据我对此主题的研究,我无法正确地从原型(prototype)继承(FireAndIce )到另一个原型(prototype)的实例(章节)。

另外,出于好奇,以下是一个坏主意吗?

通过 jQuery 创建自定义 start 事件,我可以根据需要绑定(bind)任意数量的自定义处理程序

Chapter.prototype.start = function() {
    ...
    this.initCustoms();
    this.trigger('start');
};

Chapter.prototype.initCustoms = function() {
    if(this.name === 'Fire and Ice') {
        this.on('start', function() {
            // do abc
        });
    }
    ...
};

抛开我这样做的原因不谈,这有什么问题吗?我有点喜欢为每一章提供一个 startstop 事件的想法,我可以从任何地方绑定(bind)附加功能。

提前感谢您的建议。

最佳答案

几个选项:

只需为它们分配一个函数

听起来好像只有几个 Chapter 实例,并且每一章都是一次性的(FireAndIce 章节只有一个副本),对于实例。在这种情况下,您只需创建章节实例,然后在创建它们后分配它们的 initCustoms 函数:

var fireAndIce = new Chapter();
fireAndIce.initCustoms = function() {
    // stuff for Fire and Ice
};
var secondSons = new Chapter();
secondSons.initCustoms = function() {
    // stuff for Second Sons
};
// ...

使用原型(prototype)继承和构造函数

但是如果您想通过继承来做到这一点,则如下所示:

function Chapter() {
}
Chapter.prototype.setup = function() {
    // ...chapter common stuff
};

function FireAndIce() {
    Chapter.apply(this, arguments); // Chain to parent constructor
    // ...fire and ice stuff
}
FireAndIce.prototype = Object.create(Chapter.prototype);
FireAndIce.prototype.constructor = FireAndIce
FireAndIce.prototype.initCustoms = function() {
    // ...Fire and Ice custom stuff
};

function SecondSons() {
    Chapter.apply(this, arguments); // Chain to parent constructor
    // ...Second Sons stuff
}
SecondSons.prototype = Object.create(Chapter.prototype);
SecondSons.prototype.constructor = SecondSons
SecondSons.prototype.initCustoms = function() {
    // ...Second Sons custom stuff
};

这样,FireAndIce 实例就可以共享其原型(prototype)上的 initCustoms,并且还可以共享 Chapter 原型(prototype)上的所有内容,因为 Chapter.prototypeFireAndIce.prototype 对象背后的原型(prototype)。 (SecondSons 也类似。)

请注意,如果派生函数(FireAndIceSecondSons)和 Chapter 具有不同的参数列表,则不要将所有参数传递给 Chapter 来自派生函数,您可以只传递适当的内容:

Chapter.call(this, the, appropriate, args, go, here);

使用原型(prototype)继承,不使用构造函数

有些人更喜欢使用没有构造函数的原型(prototype)继承,因此不使用 new。这也是一个选择:

var ChapterProto = {
    setup: function() {
        // ...common chapter stuff...
    }
};
function createChapter() {
    var rv = Object.create(ChapterProto);
    // ...common chapter stuff...
    return rv;
}

var FireAndIceProto = Object.create(ChapterProto);
FireAndIceProto.initCustoms = function() {
    // ...Fire and Ice custom stuff...
};
function createFireAndIce() {
    var rv = Object.create(FireAndIceProto);
    createChapter.apply(rv, arguments);
    // ...Fire and Ice stuff...
    return rv;
}

var SecondSonsProto = Object.create(SecondSonsProto);
SecondSonsProto.initCustoms = function() {
    // ...Second Sons custom stuff...
};
function createSecondSons() {
    var rv = Object.create(SecondSonsProto);
    createChapter.apply(rv, arguments);
    // ...Second Sons stuff...
    return rv;
}

同样,如果参数列表不同,您可以使用 .call 而不是 .apply

结论

对于少数对象,我更愿意在创建实例后为其分配函数。代码更少,更简单。

但是对于对象的(小写意义上的),我会使用带有构造函数的原型(prototype)继承,如上所述(但其他一些人会在没有构造函数的情况下使用它)。

<小时/>

上面使用了 Object.create,它是 ES5 中的新功能(现在大约有五年了)。如果您需要支持非常旧的引擎,您可以填充上面使用的单参数版本(第二个参数不能在 ES3 引擎上填充):

if (!Object.create) {
    Object.create = function(proto, props) {
        if (props) {
            throw "The second argument to Object.create cannot be polyfilled.";
        }

        function ctor() {
        }
        ctor.prototype = proto;
        return new ctor();
    };
}

关于javascript - 特定对象实例的自定义函数 - 我有什么可能性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26929553/

相关文章:

java - jqGrid不显示来自java的Json数据

javascript - Highchart 和 json 数据

javascript - 多个元素上的连续背景图像图案

javascript - 使用 jquery 动态添加的 css 打印 html 表

Python:自动调用所有继承的类

javascript - 如何使用 ExtJS 4 动态隐藏网格中的子列

javascript - 使用 angularJS 和输入类型 ="date"更新 mongodb 中的日期

jquery - 如何在标题中获取仅图标的控制组?

java - 带有抽象类的 RMI/事件监听器?

java - 正确使用聚合(OOP)以电子电路类为例