如果原型无法访问私有变量,那么“清理”代码的最佳方法是什么?

时间:2011-04-20 17:33:23

标签: javascript prototype scoping

嘿伙计们,我现在拥有的是:

var Human=function(){
  this._a=Math.random();
};
(function() {
  var before_get = function(human) {
  };
  var before_set = function(human, v) {
  };
  Human.prototype={
    get A(){
      before_get(this);
      return this._a;
    },
    set A(v){
      before_set(this, v);
      this._a=v;
    }
  };
})();
alert(new Human().A); // test
alert(new Human().A); // test

并且一切都很好,除了我不希望将变量 _a 暴露给除原型之外的任何其他地方。好吧,我已经做了一些搜索,并意识到这是不可能的,所以我想知道我们通常是这样离开(我的意思是我们只是留下那些_a变量飞来飞去或者是否有更好的解决方案)?

2 个答案:

答案 0 :(得分:3)

在JavaScript中没有私有这样的东西,所以这是不可能实现的。通常我们没有像其他C#/ Java那样的泛型属性或setter / getter。

可以使用的模式是闭包而不是原型。

var Human = function() {
    var a = Math.random();
    var o = {};
    Object.defineProperties(o, {
        "A": {
             "get": function() {
                 return a;
             }, 
             "set": function(val) {
                 a = val;
             }
        }
    });
    return o;
}

一般情况下,你不应该为原型写属性。原型应该包含方法。

清理this._a的唯一方法如下

var Human = (function() {
  var Human=function(){
    this._a=Math.random();
  };
  var before_get = function(human) {
  };
  var before_set = function(human, v) {
  };
  Human.prototype={
    getA(){
      before_get(this);
      return this._a;
    },
    setA(v){
      before_set(this, v);
      this._a=v;
    }
  };
  return function(args) {
     var h = new Human(args);
     return {
       getA: h.getA.bind(h),
       setA: h.setA.bind(h)
     }
  }
})();

答案 1 :(得分:1)

以下是使用原型“继承”创建私有/静态变量的方法。诀窍是在构造函数中定义原型方法(一次)。价格是你必须执行的getters / setters。利润是简单和真正的原型解决方案(毕竟这是野兽的真正本质)。顺便说一下,在这里你只创建一次'getter / setter',它就是你用它创建的所有999(999)个实例。

function Human() {
    var  a = 'We are all Human',
         o = {}
         proto = Human.prototype;
    if (!proto.A) {
       //uncomment and create a few instances to see
       //this is only executed once
       //console.log('adding prototypes');
       proto.A = function() {return a;};
       proto.set = function(val) {a = val || a;};
       proto.setName = function(val) {this.name = val || ''};
       proto.getName = function(){
           if (!this.name) {this.setName('no name yet');}
           return this.name;};
    }
}

var Pete = new Human,
    Jean = new Human;

console.log(Pete.A()+':'+Jean.A()); 
      //|=> We are all Human:We are all Human
Pete.set(Pete.A()+' except Jean'));
console.log(Pete.A()+':'+Jean.A()); 
      //|=> We are all Human except Jean:We are all Human except Jean
Pete.setName('Hi, I am Pete. '+Pete.A());
Jean.setName('Hi, I am Jean. ' +Jean.A()+ '. Damn! thats me!');
console.log(Pete.name); 
      //|=> Hi, I am Pete. We are all Human except Jean
console.log(Jean.name); 
      //|=> Hi, I am Jean. We are all Human except Jean. Damn! thats me!

你必须意识到任何人都可以决定将其他东西分配给Human.prototype.A。但是如果他们在构造函数之外执行此操作,那么闭包以及a将不再可用。