Javascript 特定对象实例的自定义函数-我有什么可能性?
因此,我目前正在构建一个相当大的框架,用于许多web项目。我很想得到以下场景的一些建议或最佳实践 我在一个web应用程序中有不同的章节。一次只能看到一个章节 第一次访问章节时调用函数Javascript 特定对象实例的自定义函数-我有什么可能性?,javascript,jquery,oop,handlebars.js,javascript-objects,Javascript,Jquery,Oop,Handlebars.js,Javascript Objects,因此,我目前正在构建一个相当大的框架,用于许多web项目。我很想得到以下场景的一些建议或最佳实践 我在一个web应用程序中有不同的章节。一次只能看到一个章节 第一次访问章节时调用函数createView()。它通过把手模板创建视图,插入XML文档中的所有副本(每种语言都有一个XML),并通过start()函数开始本章start()。它只是将视图插入DOM中,并启用所有功能,如单击事件、其他模块(图库、滑块等)等等 var Chapter = function(name) { this.n
createView()
。它通过把手模板创建视图,插入XML文档中的所有副本(每种语言都有一个XML),并通过start()
函数开始本章<每次再次访问章节时,都会调用code>start()。它只是将视图插入DOM中,并启用所有功能,如单击事件、其他模块(图库、滑块等)等等
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的lof。
那么,添加一堆if-else语句真的是一种方法吗?似乎是这样。。。肮脏的。
我还想到:
为自定义章节创建对象并继承其原型
但这只会导致继承、更改其他实例或主章节
原型方面的问题。我不想将FireAndIce
的所有功能复制到实例中,基于我对该主题的研究,我无法正确地将原型(FireAndIce
)继承到另一个原型(章节
)的实例中
另外,出于好奇,以下是一个坏主意吗
通过jQuery创建一个自定义start
事件,我可以将任意多个自定义处理程序绑定到该事件
撇开我做这件事的原因不谈,有什么问题吗?我有点喜欢为每个章节设置一个开始
和停止
事件的想法,我可以从任何地方绑定额外的功能
提前感谢您的建议。有几个选项:
只需给它们分配一个函数
听起来好像只有几个章节
实例,而且每个章节都是一次性的(例如,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
};
// ...
使用原型继承和构造函数
但是,如果您想通过继承实现这一点,下面是它的外观:
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
实例在其原型上共享initCustoms
,并且也共享章节
原型上的所有内容,因为章节.prototype
是FireAndIce.prototype
对象背后的原型。(对于次级子公司也类似)
请注意,如果派生函数(FireAndIce
、SecondSons
)和Chapter
具有不同的参数列表,而不是将所有参数从派生函数传递到Chapter
,则只需传递适当的参数即可:
Chapter.call(this, the, appropriate, args, go, here);
使用不带构造函数的原型继承
有些人喜欢使用没有构造函数的原型继承,因此不使用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
结论
对于一些对象,我更喜欢在创建实例之后将函数分配给它们。代码更少,更简单
但是对于对象类(在小写意义上),我会像上面那样使用带有构造函数的原型继承(但是其他一些人会在没有构造函数的情况下使用它)
上面使用了Object.create
,这是ES5的新功能(现在大约有五年了)。如果您需要支持非常旧的引擎,可以多填充上面使用的一个参数版本(第二个参数不能在ES3引擎上多填充):
“但这只会导致继承、更改其他实例或主章节
原型
”不,不会,不是您发布的代码。它在*instance上创建了一个prototype
属性,该属性与
章节`函数的prototype
属性或通过新章节
创建的原型基础实例完全无关。是的,我选择了一个糟糕的示例。它创建了一个prototype
属性,但我希望FireAndIce
的方法成为实例\uuuuuuuuuuuu
的一部分。为清晰起见进行了编辑。可能混入可以工作,但如果某些函数仅用于一个实例,则可以在FireAndIce中定义函数并执行FireAndIce。调用(此)使该实例具有这些函数。以下内容可能会有所帮助,因为它包含了一个混合模式,并解释了如何使用call:感谢您的详细回复。真的很感激!我喜欢您的第一种方法,但是章节
的实例不是单独创建的。每当调用另一个章节时,它们都会在循环中创建。想象一下,开发人员将使用这个框架来创建一本虚拟书。因此:我需要一种方法,让其他开发人员通过自定义功能“钩住”章节,我尝试在这里提供一种方法。因此,在创建章节
的实例后,我无法声明自定义函数,因为我不知道会有什么实例。您的第二种和第三种方法是我最初想到的。问题是:章节
的一个实例已经并始终存在。现在,其中一些实例将需要自定义功能。所以这并不是说我可以用不同的原型/构造器重新创建章节。我需要以某种方式包含/导入来自定制原型(由其他人制作)的所有方法,以便
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
};
Chapter.call(this, the, appropriate, args, go, here);
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;
}
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();
};
}