在构造函数中向原型添加属性

adi*_*aur 2 javascript constructor prototype-programming

我正在尝试一些示例,并遇到一个问题,如果我们想要向原型添加一个函数,它将无法访问构造函数的私有成员.我遇到了这个解决方案.这似乎是一个很好的黑客.

我尝试了其他一些方法,我得到以下内容:

var Restaurant = function()
{
    var myPrivateVar;
    var private_stuff = function()   // Only visible inside Restaurant()
    {
        return "I can set this here!";
    }
    Restaurant.prototype.use_restroom = function()   // use_restroom is visible to all
    {
        private_stuff();
    }
    Restaurant.prototype.buy_food = function()    // buy_food is visible to all
    {
        return private_stuff();
    }
}
var restaurant = new Restaurant();
restaurant.buy_food(); // this would work
restaurant.private_stuff(); // this won't
Run Code Online (Sandbox Code Playgroud)

解决方案似乎很奇怪,因为我们在构造函数中添加了原型.(我没有看到太多这个).它至少适用于firefox 5和chrome.它有什么问题吗?

Ski*_*ick 11

你正在做的是每次制作一个新的餐馆对象时在原型上重新定义这些方法.更明智的方法是定义它们this,这是在构造函数中构造的新对象:

var Restaurant = function()
{
    var myPrivateVar;
    var private_stuff = function()   // Only visible inside Restaurant()
    {
        return "I can set this here!";
    }
    this.use_restroom = function()   // use_restroom is visible to all
    {
        private_stuff();
    }
    this.buy_food = function()    // buy_food is visible to all
    {
        return private_stuff();
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以这样做,但不要使用new:

var RestaurantMaker = function () {
  var myPrivateVar;
  var private_stuff = function() {
    return "I can set this here!";
  }

  return {
    use_restroom: function () {
      private_stuff();
    },
    buy_food: function () {
      return private_stuff();
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

然后就是:

var restaurant = RestaurantMaker();
Run Code Online (Sandbox Code Playgroud)

这被称为揭示模块模式.缺点是每个新对象都会获得所有函数的副本,如果this在构造函数中添加方法,也会发生这种情况.

一个非常小的替代版本的揭示模块模式(我认为读得更好)看起来像这样:

var RestaurantMaker = function () {
  var myPrivateVar;

  function private_stuff() {
    return "I can set this here!";
  }

  function use_restroom() {
    private_stuff();
  }

  function buy_food() {
    return private_stuff();
  }

  return {
    use_restroom: use_restroom,
    buy_food: buy_food
  };
}
Run Code Online (Sandbox Code Playgroud)

然后,如果要更改函数是否为私有,则只需在返回的对象中添加或删除它即可.