过去几个月我一直在使用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));
哪个更好,为什么?
答案 0 :(得分:4)
JS实际上并没有私有方法,但正如您所见,您可以通过关闭其范围来限制对函数和变量的访问。
最后,如果它在原型上,它不是私有的 - 无论命名约定(引导下划线等)。因此,如果确实想限制对某些内容的访问,请将 NOT 放在原型上。
答案 1 :(得分:2)
将函数放在局部范围内的第二种模式更可取,因为它实际上是私有的。但它并不是真正的OOP。
第一种模式,将函数放在原型的下划线属性中是可取的,因为它们是实际的方法,它们会像您期望的方法一样隐式传递this
。通过实例方法,它们可用于任何需要它们的模块,而不受范围限制,这在大型项目中可能是有益的。当然,方法在OOP中很重要,因为如果你想使用多态,它们会提供动态调度。
同样原型方法(对吗?)进行了更好的优化,所以如果你需要挤出最后一点性能,它们就被选中了,但实际上你看不出普通函数调用会有多大区别。
答案 2 :(得分:0)
对象或子类可以访问附加到函数的prototype属性的任何方法。 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
是一个私有方法,不能在范围之外修改/覆盖。