实例共享原型方法以与私有实例变量一起使用

发布于 2024-11-07 09:09:23 字数 2186 浏览 6 评论 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;
}

Human 添加 get/set 原型方法

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 世界中,有时看起来每个人都给术语赋予了自己的私有含义) 。

不管怎样,我在这个jsfiddleHuman >。

  • [edit1] 回应评论:放弃了立即调用函数 (iif)
  • [edit2] 没有 .caller 的较少私有替代方案,但仍然可以使用私人存储:请参阅 this jsfiddle
  • [edit3] 可能是好吧也放弃原型
  • [edit4]为了完整:这是一个正版原型获取/设置变体

This SO-question kept bugging me. It's a question that seems to reappear on a regular basis in SO.

Now I've deviced a way to create a constructor function trying to manage that private 'properties' can only be set from the constructors prototype get/set methods, using a private storage. In it's basic form it looks like this:

The basic constructor function:

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

Adding get/set prototype methods to 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'

I am really interested in your comments. Maybe I am thinking in a completely wrong direction, maybe you say it's an unnecessary operation, violating the prototypal nature of js, it already has been done (and better) elsewhere, or anything. Please tell me!

What I think of this - well here let's call it - pattern: what you loose using it is the ease of simply declaring and getting properties (this.some = that etc.), what you win is better encapsulation, privacy of instance variables and some control over the properties you use (not sure if it's the right terminology, but then again in the OOP world it sometimes looks like everyone gives it's own private meaning to terminology).

Anyway, I've cooked a more complete and working Human in this jsfiddle.

  • [edit1] In response to comment: ditched the immediately invoke function (iif)
  • [edit2] Less private alternative without .caller, but still able to use the private storage: see this jsfiddle
  • [edit3] Might as well ditch the prototype too
  • [edit4] To be complete: here's a genuine prototypal get/set variant

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

帅气尐潴 2024-11-14 09:09:23

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

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


无意冒犯,但代码设计过度、复杂,阅读或维护起来似乎很痛苦。我没有看到这种方法有什么优点?为什么不直接让 this._store 成为一个特权函数呢?

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


至于代码批评:

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

this._store = {get:get};

为什么不只是 this._store = get

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

应该内联到

返回存储[prop]

First of all what is this overly engineered solution trying to solve?

The problem with trying to access constructor local variables from the prototype is not a problem. People either need to only use the prototype and store all the data on this for a minor speed gain or not complain about creating extra functions for each object (minimal overhead). It's a common misunderstanding that creating extra functions for each object is expensive.


No offence but the code is over engineered, complex and seems like a right pain to read or maintain. I don't see any advantages in this method? Why not just make this._store a privileged function.

Also the fact that you have a local function in your constructor means you lose that advantage with the prototype of having one function for all objects. I've also over engineered a solution similar to this to "emulate" private variables, the code became a right mess to work with and I had to abandon it.


As for code critism:

.caller is non standard. You can't use it. It's a hack.

this._store = {get:get};

Why not just this._store = get ?

This

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

should be inlined to

return storage[prop]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文