【问题标题】:OOP Javascript: Should Private Functions Be Added to Class Prototype?OOP Javascript:应该将私有函数添加到类原型中吗?
【发布时间】:2016-07-30 18:18:39
【问题描述】:

背景

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

问题

哪些更可取,为什么?

【问题讨论】:

  • _init 方法几乎总是一种反模式。只需将初始化权放在构造函数中即可。
  • 这取决于您是否希望能够在闭包之外访问这些方法。
  • 为什么使用_init 是反模式?
  • @AndyM:正如我所说,初始化应该在构造函数中。无需将其提取到额外的方法中。

标签: javascript oop


【解决方案1】:

JS 实际上没有私有方法,但正如您所见,您可以通过关闭函数和变量的范围来限制对函数和变量的访问。

最后,如果它在原型上,它就不是私有的——不管命名约定(前导下划线等)。因此,如果您真的想要限制对某些东西的访问,请将它放在原型上。

【讨论】:

  • 感谢您的回答,非常感谢,赞成。不过,我将 Bergi 标记为解决方案,因为它包含有关我所询问的两个选项的信息,而且更深入一些。 (希望我可以将两者都标记为解决方案)。不过谢谢!
【解决方案2】:

第二种模式,将函数放在本地范围内,更可取,因为它实际上是私有的。但这并不是真正的 OOP。

第一种模式,将函数放在原型上的下划线属性中,更可取,因为它们是实际方法,可以像您期望的方法一样隐式传递其this。作为实例方法,它们可供任何需要它们的模块使用,而不是受到范围的限制,这在大型项目中可能是有益的。当然,方法在 OOP 中也很重要,因为如果您想使用多态性,它们会提供动态调度。

原型方法也(曾经?)进行了更好的优化,因此如果您需要挤出最后一点性能,则选择它们,尽管在实践中您不会看到与普通函数调用有太大区别。

【讨论】:

  • 我很欣赏这两种选择的原因。我现在对细微的性能差异感到好奇,所以有时间我会设置 jsperf 测试。
【解决方案3】:

任何附加到函数原型属性的方法都可以被对象或子类访问。所以,

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

【讨论】:

    猜你喜欢
    • 2016-08-17
    • 1970-01-01
    • 2010-12-06
    • 2013-08-02
    • 2020-06-09
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多