使用模块全局作用域定义可从prototype访问的私有类字段

use module global scope to define private class fields accessible from prototype

本文关键字:访问 字段 prototype 模块 全局 作用域 定义      更新时间:2023-09-26

如果一个构造函数和它的原型是在同一模块中定义的,说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;
    };

?

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!');
当然,这并不是说在任何情况下都不需要依赖构造函数来处理它的副作用。但是在你给出的例子中,它甚至看起来不像一个构造函数是必要的(尽管我理解这个例子只是为了演示问题而设计的)。

在哪里以及如何使用_下划线是不相关的,只是作为旁注。它们在某些情况下很好,比如区分伪私有属性和"公共"属性,但我认为这更像是一种惯例,而不是一种固定不变的模式。