使用模块全局范围来定义可从原型访问的私有类字段

时间:2015-08-08 04:13:16

标签: javascript

如果构造函数及其原型是在同一模块中定义的,比如AMD模块,是否可以使类私有字段全局化,以便在原型中可以访问模块,而不是在构造函数中使用下划线定义它们?

这样做更好:

define(function (require) {
    "use strict";

    var steps = 0;

    function Constructor(_steps) {
        steps = _steps;
    }

    Constructor.prototype.go = function () {
        steps += 1;
    };

然后这个:

define(function (require) {
    "use strict";

    function Constructor(_steps) {
        this._steps = _steps;
    }

    Constructor.prototype.go = function () {
        this._steps += 1;
    };

1 个答案:

答案 0 :(得分:2)

TL; DR:并不重要(这只是一个小的实现细节)

两种不同的解决方案。一个不一定比另一个“更好”,它们只是有不同的用例。

如果您正在使用构造函数/原型模式,那么在面向对象的意义上,在实例本身上设置构造函数参数是有意义的(使用this.<whatever-prop>)。当您决定仅为了其副作用而使用构造函数时(通过根据传递给构造函数的参数设置someModuleVariable),它可能会不必要地混淆代码。

然而,拥有一个可供整个模块访问的“私有”变量是一种非常常见的模式......例如,当使用单例对象时,因为当您离开函数的执行上下文时,范围变量永远不会被销毁,模块仍然可以查询“module-local”变量。

唯一让我错误的方法是使用构造函数只是为了它的副作用...为什么我会使用构造函数然后,当构造函数的一个主要目的是隐式设置属性时实例?

要区分这两个想法,一个常见的模式是在原型中使用init方法,因为 是一个很好的地方,可以包含所有你想要的副作用。例如,人们可以建议这样做:

var Module = (function() {
  var somethingPrivate;

  function SomeObject(someProp) {
    // rely on the constructor to set instance properties
    this.someProp = someProp;
  }

  SomeObject.prototype = {
    init: function(_somethingPrivate) {
      // all of your side effects in here, such as:
      somethingPrivate = _somethingPrivate;
    }
  };

  return SomeObject;
}());

var module = new Module('Hello world! I belong to the instance');

module.init('I am a module-specific variable!');

然而,当然,这并不是说在某些情况下您可能不希望依赖构造函数来产生副作用。但是在你给出的例子中,它甚至看起来不像构造函数是必要的(尽管我理解这个例子只是为了演示问题而设计的。)

使用_下划线的位置和方式大多不相关,只是作为旁注。在某些情况下,它们是好的,比如将伪私有属性与“公共”属性区分开来,但我认为这更像是一种约定,而不是一种刻板的模式。