0

这个问题一直困扰着我。这是一个似乎在 SO 中定期重新出现的问题。

现在我已经设计了一种方法来创建一个构造函数,试图管理私有“属性”只能从构造函数原型 get/set 方法中设置,使用私有存储。它的基本形式如下所示:

基本构造函数:

function Human(){
   /** set up a property storage **/   
   var storage = {
      name: { val: name || '-', get:true, set:true }
      ,age: { val: (age || '0'), get:true, set:true }
   };
   function get(){
       if (get.caller !== Human.prototype.get &&
           get.caller !== Human.prototype.set ){ return null }
       return storage;
   }
   this._get = get;
}

将 get/set 原型方法添加到Human

Human.prototype = {
     get: function(prop){
        return this._get()[prop];
     }
    ,set: function(prop, val){
       var storage = this._get();
       /** 
              set functionallity, returning 
              the current object after setting
              see jsfiddle link @ the bottom of
              this question
        **/
       return this;
    }
};
// usage
var pete = new Human('Pete',23);
pete.get('name'); //=> 'Pete'
pete.set('name','Pete Justin');
pete.get('name'); => 'Pete Justin'
// but
pete.name; //=> 'undefined'

我对你的评论很感兴趣。也许我在想一个完全错误的方向,也许你说这是一个不必要的操作,违反了 js 的原型性质,它已经在其他地方完成(并且更好),或者任何事情。请告诉我!

我对此的看法——好吧,我们称之为——模式:你使用它松散的是简单地声明和获取属性(this.some = that等),你赢得的是更好的封装、实例变量的隐私和对属性的一些控制您使用(不确定它是否是正确的术语,但是在 OOP 世界中,有时看起来每个人都对术语赋予了自己的私人含义)。

无论如何,我已经Human这个 jsfiddle中做了一个更完整的工作。

  • [编辑1 ]回应评论:放弃立即调用功能(iif)
  • [ edit2 ] 没有 的较少私有替代方案.caller,但仍然能够使用私有存储:请参阅此 jsfiddle
  • [ edit3 ] 还不如放弃原型
  • [ edit4 ] 完整:这是一个真正的原型 get/set 变体
4

1 回答 1

2

首先,这个过度设计的解决方案试图解决什么?

尝试从原型访问构造函数局部变量的问题不是问题。人们要么只需要使用原型并存储所有数据以this获得较小的速度增益,要么不必抱怨为每个对象创建额外的功能(最小开销)。一个常见的误解是为每个对象创建额外的函数是昂贵的。


没有冒犯,但代码设计过度,复杂,阅读或维护似乎很痛苦。我看不出这种方法有什么好处?为什么不做this._store一个特权函数。

此外,您在构造函数中有一个本地函数这一事实意味着您失去了对所有对象都有一个函数的原型的优势。我还过度设计了一个与此类似的解决方案来“模拟”私有变量,代码变得一团糟,我不得不放弃它。


至于代码批评:

.caller是非标准的。你不能使用它。这是一个黑客。

this._store = {get:get};

为什么不只是this._store = get

function thisget(prop){
    return storage[prop];
}
return thisget(prop);

应该内联到

return storage[prop]

于 2011-05-15T20:43:28.477 回答