Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript dynamically getter/setter for private properties

I want to create getter/setter methods dyanmically to retrieve private properties.

This is what I did.

First of all, I made the class:

function winClass (posX, posY, w, h) {
  var x = posX || 0;
  var y = posY || 0;
  var width = w || 0;
  var height = h || 0;
}

Then I extended winClass with getter/setter methods, as follows:

winClass.prototype.getX = function () {
  return x;
}

winClass.prototype.setX = function (val) {
  x = val;
}

And then I tested:

var win1 = new winClass (10, 10, 100, 100);
document.write (win1.getX ());

But the following error comes when I try to setup the 'getX' method: 'x is not defined'. It makes sense because that 'x' isn't in the winClass scope but thus I don't know how to setup dynamically getter/setter methods for private variables.

Any ideas?

like image 623
Wilk Avatar asked Aug 28 '11 20:08

Wilk


1 Answers

The getter/setters have to be in the scope that can see the private variables and the only scope that can see these variables is the internals of the constructor. That's why these variables are actually private. So, to make setters/getters for them, you have to put the functions in that scope that can see them. This will work:

function winClass (posX, posY, w, h) {
  var x = posX || 0;
  var y = posY || 0;
  var width = w || 0;
  var height = h || 0;

  this.getX = function() {return(x);}
  this.setX = function(newX) {x = newX;}
}

var win1 = new winClass (10, 10, 100, 100);
alert(win1.getX());   // alerts 10

You can see it work here: http://jsfiddle.net/jfriend00/hYps2/.

If you want a generic getter/setter for privates, you could do it like this:

function winClass (posX, posY, w, h) {
  var privates = {};
  privates.x = posX || 0;
  privates.y = posY || 0;
  privates.width = w || 0;
  privates.height = h || 0;

  this.get = function(item) {return(privates[item]);}
  this.set = function(item, val) {privates[item] = val;}
}

var win2 = new winClass(10,10,100,100);
alert(win2.get("x"));    // alerts 10

And, if you want to hack around the private nature of these variables which makes no sense to me (as you might as well make them standard instance variables then), you can do it like this:

function winClass (posX, posY, w, h) {
  var privates = {};
  privates.x = posX || 0;
  privates.y = posY || 0;
  privates.width = w || 0;
  privates.height = h || 0;

  this.getPrivates = function() {return(privates);}
}

winClass.prototype.getX = function() {
    return(this.getPrivates().x);
}

winClass.prototype.setX = function(newX) {
    this.getPrivates().x = newX;
}

Example here: http://jsfiddle.net/jfriend00/EKHFh/.

Of course, this ruins the private nature of the variables so there isn't really any point in doing it this way as making them regular instance variables would be easier and have the same access control.

And, for completeness, here's the normal instance variable method that freely lets you add accessor methods to the prototype, but the variables aren't private.

function winClass (posX, posY, w, h) {
  this.x = posX || 0;
  this.y = posY || 0;
  this.width = w || 0;
  this.height = h || 0;
}

winClass.prototype.getX = function() {
    return(this.x);
}

winClass.prototype.setX = function(newX) {
    this.x = newX;
}
like image 176
jfriend00 Avatar answered Oct 14 '22 02:10

jfriend00