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

时间:2015-11-09 14:53:14

标签: javascript ecmascript-5

当我们在原型对象中声明一个方法时,我们只在内存中有一个位置,我们可以稍后调用方法,但是使用 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;
    }
}

从我理解的内容(请纠正我,如果我错了)这是我如何创建一个私有方法,如果我们需要,这似乎是一个坏主意创造了很多孩子,还是我错过了这一点?

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

您定义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。希望这能说明您何时考虑使用私有状态与原型上公开提供的方法。

答案 1 :(得分:0)

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

请注意,这可能会使单元测试成为一项挑战,但在Node.js中,您可以使用类似rewire的内容来访问私有函数。

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

  getFullName.call( this );
}

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