Следует ли использовать геттеры и сеттеры для частных переменных?

Я использую такие объекты JavaScript:

var obj = new Foob;

я должен притвориться, что есть частный способ, и сделать:

obj.get('foo');

или я должен просто попытаться получить доступ напрямую как:

obj.foo

person Community    schedule 21.04.2013    source источник
comment
Зависит от цели и от того, требует ли ситуация. Но в JS в любом случае нет ничего приватного.   -  person Joseph    schedule 22.04.2013
comment
вот почему я сказал pretend   -  person    schedule 22.04.2013
comment
Как насчет js-геттеров и сеттеров? stackoverflow.com /вопросы/15735821/   -  person louisbros    schedule 22.04.2013
comment
... я знаю о геттерах/сеттерах   -  person    schedule 22.04.2013
comment
Ну, вы не упомянули их в своем вопросе. Вместо этого вы спросили, следует ли вам использовать get('foo'), что было бы довольно странным способом предоставления этого свойства.   -  person JLRishe    schedule 22.04.2013
comment
геттеры/сеттеры CS101   -  person    schedule 22.04.2013


Ответы (3)


На самом деле у вас могут быть переменные, к которым можно получить доступ только через сеттеры и геттеры в Javascript:

function Foob(){

    var foo = 5;

    this.getFoo = function(){
        return foo;
    }


    this.setFoo = function(newFoo){
        foo = newFoo;
        return this;
    }

}

var obj = new Foob;
obj.getFoo(); // 5
obj.foo; // undefined

Или, если вам нужен общий геттер/сеттер:

function Foob(){

    // You can set default values in the data object
    var data = {};

    this.get = function(key){
        return data[key];
    }

    this.set = function(key, value){
        data[key] = value;
        return this;
    }

}
person Paul    schedule 21.04.2013
comment
Какая разница, если что-то делать... Foob.prototype.setFoo = function ... и this.setFoo = function ... - person ; 22.04.2013
comment
Я помню, почему я не делаю этого сейчас... потому что сейчас вы создаете новую функцию для каждого экземпляра объекта. - person ; 22.04.2013
comment
@pure_code Когда вы используете прототип, все экземпляры Foob используют одну и ту же функцию. Когда вы используете this, каждый экземпляр имеет свою собственную версию функции, и эта функция находится во внутренней области конструктора, поэтому она может получить доступ к переменной data. - person Paul; 22.04.2013
comment
@pure_code На самом деле нет ничего плохого в том, что каждый экземпляр имеет свою собственную функцию, если только вы не создаете сотни тысяч экземпляров. Особенно, если вы делаете универсальную версию, которая требует, чтобы у вас были только две функции, определенные таким образом для любого количества частных переменных. - person Paul; 22.04.2013
comment
@pure_code В общем, вы должны использовать прототип, когда это возможно, но когда это невозможно (вы хотите, чтобы ваши функции имели доступ к переменным, определенным в области конструктора), вам не следует полностью избегать этого. - person Paul; 22.04.2013
comment
@pure_code Да, решать вам. Предпочитаете ли вы, чтобы каждый экземпляр имел свои собственные функции и частные переменные, или ни то, ни другое. Есть компромисс. - person Paul; 22.04.2013

Одна из наименее известных особенностей Javascript заключается в том, что он изначально поддерживает геттеры и сеттеры.
При определении свойства вы можете определить его просто:

someObj.prop = 12;

ИЛИ вы можете определить геттеры и сеттеры, используя Object.defineProperty и зарезервированные слова get и set:

Object.defineProperty ( someObj,    "prop" ,  
                                              { get : function () { return ??; } ,
                                                set : function (val) { /* store val */ }            } ;

Способ использования таких геттеров/сеттеров внутри «класса» для получения частной переменной:

var MyClass = function() {
  var _private = 5;
  
  Object.defineProperty(this, "public", {
    get : function() { return _private; },
    set : function(val)  { _private=val; }
  });
  
  return this;
};

var anInstance = new MyClass();

anInstance.public = 12 ; 
console.log(anInstance.public)   ;  // writes 12
console.log(anInstance._private) ;  // writes undefined. 

так что у вас есть действительно частная переменная, вооруженная геттером и сеттером.

Очевидно, что нет особого интереса использовать код геттеров/сеттеров, если только вы не хотите выполнять проверку привязки/проверку типов или у вас есть другая конкретная причина.

person GameAlchemist    schedule 21.04.2013

Раньше мне нравилась идея геттеров и сеттеров, когда я начал интенсивно использовать объектно-ориентированный JavaScript, но это потому, что я пришел из Java.

ES5 поддерживает геттеры и сеттеры через специальный синтаксис.

См. объяснение Джона Резига:

http://ejohn.org/blog/javascript-getters-and-setters/

Я думаю, почему геттеры/сеттеры полезны. Это значит, что у вас есть способ инкапсулировать доступ к переменной, чтобы его можно было перехватить/контролировать. Если вызывающий код напрямую изменяет переменные экземпляров другого объекта, вы не можете изменить его прозрачно. Необходимость поймать все эти мутации требует изменения области видимости переменной, добавления геттера и сеттера и изменения всего вызывающего кода.

Однако этот синтаксис прозрачен для вызывающего кода. Следовательно, вы можете просто разрешить прямое управление свойством, а затем, если вам нужно его перехватить, например, добавить console.log для отладки, вы можете ДОБАВИТЬ геттер и сеттер, и он просто будет работать.

function Foob() {
}
Foob.prototype = {
  get foo() {
    return this._foo;
  },
  set foo(foo) {
    this._foo = foo;
  }
};

var o = new Foob();
console.log(o.foo);

Недостатком синтаксиса getter/setter является то, что он фактически не делает вашу переменную частной, а только «скрывает» ее, чтобы вы могли использовать какое-то секретное внутреннее имя, если только вы не определили его в конструкторе, как указал Винсент.

Чтобы стать по-настоящему приватным:

function Foob() {
  var foo;
  this.__defineGetter__('foo', function () { 
    return foo;
  });
  this.__defineSetter__('foo', function (_foo) {
    foo = _foo;
  });
}

var o = new Foob();
console.log(o.foo);
person Brandon    schedule 21.04.2013
comment
Спасибо. Мне больше нравится defineProperty. Забыл все об этом - но определенно чище. - person Brandon; 22.04.2013