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)); 

问题

哪一个是最好的,为什么?

+0

'_init'方法几乎总是一个反模式。只需在构造函数中使用初始化权限即可。 – Bergi

+0

这取决于您是否希望能够在闭包之外访问这些方法。 – Oriol

+0

为什么使用'_init'是反模式? –

第二种模式,将函数放在本地作用域中,因为它实际上是私有的,所以更好。但它不是真的OOP。

第一种模式是将函数放在原型的下划线属性上,因为它们是实际的方法,它们的默认方式就像您期望的方法那样传递。通过实例化方法,任何需要它们的模块都可以使用它们,而不受范围的限制,这对于大型项目可能是有益的。当然,如果你想使用多态性,方法在面向对象方面很重要,因为它们提供动态调度。

此外,原型方法还有一些更好的优化,所以如果您需要排除性能的最后一点,它们会被选中,尽管在实践中您不会看到与普通函数调用有很大区别。

+0

我很欣赏这两种选择的原因。我现在对这种轻微的性能差异感到好奇,所以当我抽出一些时间时,我会设置jsperf测试。 –

JS实际上并没有私有方法,但正如你所看到的,你可以通过关闭范围来限制对函数和变量的访问。最后,如果它在原型上,它不是私有的 - 不管命名约定(主要下划线等)如何。所以如果你真的想限制访问的东西,做不是把它放在原型。

+0

感谢您的答复,非常感谢,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上面的例子中是一个私有方法,不能被修改/覆盖范围之外。