если прототипы не могут получить доступ к закрытым переменным, каков наилучший способ «очистить» код? - PullRequest
2 голосов
/ 20 апреля 2011

Эй, ребята, теперь у меня есть следующее:

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 где-либо еще, кроме прототипа.Хорошо, я провел некоторый поиск и понял, что это невозможно, поэтому мне было интересно, мы обычно оставляем это как есть (я имею в виду, мы просто оставляем эти переменные _ летать или есть лучшее решение)?

Ответы [ 2 ]

3 голосов
/ 20 апреля 2011

В JavaScript нет такого понятия, как приватность, поэтому это недостижимо.Как правило, у нас нет общих свойств или методов установки / получения, как у других C # / Java.

Шаблон, который можно использовать, это замыкания вместо прототипов.

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 голос
/ 20 апреля 2011

Вот как вы создаете подобные приватные / статические переменные, используя прототип наследования. Хитрость заключается в том, чтобы определить методы-прототипы внутри конструктора (один раз). Цена геттеры / сеттеры, которые вы должны выполнить. Прибыль - это простота и истинное прототипное решение (которое, в конце концов, и есть настоящая природа зверя). И, между прочим, здесь вы создаете свой '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 больше не доступны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...