OOP Javascript:是否应该将私有函数添加到类原型中?

时间:2016-07-30 18:18:39

标签: javascript oop

背景

过去几个月我一直在使用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));

问题

哪个更好,为什么?

3 个答案:

答案 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是一个私有方法,不能在范围之外修改/覆盖。