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

Private methods within constructor (Javascript, bad idea?)

本文关键字:Javascript 有方法 构造函数      更新时间:2023-09-26

当我们在原型对象中声明一个方法时,我们在内存中只有一个位置,稍后我们可以在其中调用方法。然而,使用private方法的思想,每次创建新的子对象时,我们都会在内存中重新创建方法。

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

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');

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

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

根据我的理解(如果我错了,请纠正我),这就是我创建私有方法的方式,如果我们需要创建很多孩子,这似乎是个坏主意,或者我只是错过了重点?

有什么想法吗?

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

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

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();
}

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

私有方法作为"实用程序"类型的方法通常是有意义的。例如,考虑以下内容:

// 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;
}