构造函数中的私有方法(Javascript,坏主意?)

Private methods within constructor (Javascript, bad idea?)

当我们在原型 object 中声明一个方法时,我们只是在内存中有一个位置,我们稍后可以在其中调用方法,但是使用 private 的想法每次我们创建一个新的 child.

方法时,我们都会 re-create 内存中的方法

为了直观起见,请查看下面的两个结构:

function Person(firstname, lastname){
  this.firstname = firstname,
  this.lastname = lastname
}

Person.prototype.getFullName = function() {
  return this.firstname + ' ' + this.lastname;
}

var ham = new Person('Hamoodi', 'Josef');

好的,上面的代码创建了一个方法并将其存储在我们的原型中 object,太棒了。

function Person(firstname, lastname){
  this.firstname = firstname,
  this.lastname = lastname,

    this.getFullName = function() {
      return this.firstname + ' ' + this.lastname;
    }
}

根据我的理解(如果我错了请纠正我)这就是我创建 private 方法的方式,如果我们需要,这似乎是个坏主意创造许多 children,还是我只是错过了重点?

有什么想法吗?

您定义 getFullName 函数的方式没有任何隐私。它将在任何 Person 个实例上可用,并在每个实例中复制。这就是为什么将方法放在 Constructor 的原型上以便它们在实例之间共享的原因。

如果你的构造函数中真的有一个私有函数,它看起来像这样:

function Person(firstname, lastname){
  // bind the function to this instance
  var getFullName = (function () {
      return this.firstname + ' ' + this.lastname;
  }).bind(this);

  this.firstname = firstname;
  this.lastname = lastname;
  // call private function and set property
  this.fullName = getFullName();
}

这再次受到负面影响,即每个实例都会创建自己的私有方法副本(但至少这次它的作用域实际上是私有的)。

私有方法通常与 "utility" 类型方法一样有意义。例如,考虑以下内容:

// your javascript file
(function (global) {

    // private scope
    var id = 0,
    getId = function () {
        return ++id;
    };

    function Person(firstname, lastname) {
        // call private method to get id
        this.id = getId();
        this.firstname = firstname;
        this.lastname = lastname;
    }

    // expose globally
    global.Person = Person;

}(window));

现在,当有人使用您的 API 创建一个新人时,它会使用私有可用的 getId 函数为该人分配一个唯一的 ID。希望这表明您何时会考虑使用私有状态与原型上公开可用的方法。

在给定模块中获取私有方法的一种方法是将它们定义在其他 API 消费者无法访问的范围内。

请注意,这会给单元测试带来挑战,但在 Node.js 中,您可以使用 rewire 之类的东西来访问私有函数。

function Person(firstname, lastname){
  this.firstname = firstname,
  this.lastname = lastname,

  getFullName.call( this );
}

function getFullName() {
  return this.firstname + ' ' + this.lastname;
}