OOP Javascript:应该将私有函数添加到类原型中吗?
背景
过去几个月我一直在使用OOP风格的Javascript,从解剖开源库开始。看起来他们大多遵循相同的模式,除了我已经看到了处理私有函数的两种方法,并且我在想哪个是最好的(最好像最佳实践一样,或者因为我可能不知道的原因而更好)。OOP Javascript:应该将私有函数添加到类原型中吗?
示例代码
下面是我正在使用的模式的一个非常简洁的骨架。如果你会注意到,有两种不同形式的私人功能。
第一个附属于原型,如公共功能,但带有前缀_
。
第二个只是一个功能,它的范围只能由该类访问。
(function(window) {
window.FooBarClass = (function() {
var Class = function(params) {
this._init(params);
}
/***************************************/
/************* INITIALIZE **************/
/***************************************/
Class.prototype._init = function(params) {
// DO SETUP STUFF
};
/***************************************/
/********** PUBLIC FUNCTIONS ***********/
/***************************************/
Class.prototype.doThings = function() {
// DO STUFF
};
/***************************************/
/****** PRIVATE FUNCTIONS 1ST WAY ******/
/***************************************/
Class.prototype._createSection = function(params) {
// DO STUFF
};
/***************************************/
/****** PRIVATE FUNCTIONS 2ND WAY ******/
/***************************************/
function correctTwoDigitYear(variable) {
// DO STUFF
}
return Class;
}());
}(window));
问题
哪一个是最好的,为什么?
第二种模式,将函数放在本地作用域中,因为它实际上是私有的,所以更好。但它不是真的OOP。
第一种模式是将函数放在原型的下划线属性上,因为它们是实际的方法,它们的默认方式就像您期望的方法那样传递。通过实例化方法,任何需要它们的模块都可以使用它们,而不受范围的限制,这对于大型项目可能是有益的。当然,如果你想使用多态性,方法在面向对象方面很重要,因为它们提供动态调度。
此外,原型方法还有一些更好的优化,所以如果您需要排除性能的最后一点,它们会被选中,尽管在实践中您不会看到与普通函数调用有很大区别。
我很欣赏这两种选择的原因。我现在对这种轻微的性能差异感到好奇,所以当我抽出一些时间时,我会设置jsperf测试。 –
JS实际上并没有私有方法,但正如你所看到的,你可以通过关闭范围来限制对函数和变量的访问。最后,如果它在原型上,它不是私有的 - 不管命名约定(主要下划线等)如何。所以如果你真的想限制访问的东西,做不是把它放在原型。
感谢您的答复,非常感谢,upvoted。尽管如此,我将Bergi列为解决方案,因为它具有关于我所问的两个选项的信息,更深入一点。 (希望我可以将这两个标记为解决方案)。谢谢你! –
附加到函数原型属性的任何方法均可由对象或子类访问。 SO,
class.prototype.__init
不能被视为私有方法。 它可以由对象是入店或它可以通过扩展类 前进行修改:
var someClass = (function() {
var Class = function(params) {
this._init(params);
}
Class.prototype._init = function(params) {
console.log("Hello World");
};
return Class;
}());
var extendSomeClass = someClass;
extendSomeClass.prototype._init = function() {
console.log("Hey there");
}
var obj = new extendSomeClass(); // this wil print "Hey there"
在你已经张贴的例子中,_init
充当构造,因此与其相关联的属性是公开(尽管命名约定建议私人成员)。但要遵循私人访问,封闭范围应该是最佳实践。 例如:
var fooClass = (function() {
var Class = function() {
if(this._init) {
this._init.apply(this, arguments);
}
}
Class.prototype.hello = function() {
log("hello world");
}
function log(args) {
console.log(args);
}
}());
在功能log
上面的例子中是一个私有方法,不能被修改/覆盖范围之外。
'_init'方法几乎总是一个反模式。只需在构造函数中使用初始化权限即可。 – Bergi
这取决于您是否希望能够在闭包之外访问这些方法。 – Oriol
为什么使用'_init'是反模式? –