0

One way to define a class in Javascript is with closures and the object literal. As an example, consider a circle:

var circle = function(radius) {
    var radius = radius;
    return {
        area: function() { 
            return Math.PI*(radius*radius); 
        }
    }
}

Circle objects can then be instantiated with the internal variables remaining encapsulated:

c = circle(1);
c.area(); // Returns pi
c.radius; // Returns undefined

Unfortunately with this method, if I was to create multiple circles the area function would be copied for each instance. This is where the prototyping is usually used:

var Circle = function(radius) {
    this.radius = radius;
}
Circle.prototype.area = function() { 
    return Math.PI*(this.radius*this.radius); 
};

Now the problem is that variables cannot be declared private:

c = new Circle(1); 
c.area(); // Returns pi 
c.radius; // Returns 1

Does anyone know how I would get the best of both? Efficiency is an issue so would rather avoid the current formulation of the first method, and I am writing for a public API so don't want users to have access to internal variables/methods. Thanks in advance...

warrd
  • 1

2 Answers2

1

How about this:

function Circle(radius) {
    this.getRadius = function() { return radius; }
}

Circle.prototype.area = function() {
    var r = this.getRadius();
    return Math.PI * r * r; 
};

Now each instance of the Circle pseudo-class has two methods:

  • area which is inherited from the prototype thus making it a public method
  • getRadius which is assigned to the instance object thus making it an instance method

The radius value is still retrievable via getRadius though. However, if getRadius could determine whether it's called from within a Circle.prototype method and only return the radius value if it is, then that would solve it, but I'm not sure that that can be done.

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
0

This is what I came up with, though whether creating the GetArea() method everytime is "efficient" I doubt, but it's the only way I'm aware of to access the a local scope variable from prototype methods:

var Circle = (function(){
    var Circle = function(radius) {
        this.GetRadius = function(){
            return radius;
        }
    };
    Circle.prototype.area = function() {
        var rad = this.GetRadius();
        return Math.PI*(rad*rad); 
    };
    return function(radius){
        return new Circle(radius);
    }
})();

(This will allow access to the value of the Radius of the circle, but not allow you to change it, which is why I presume you wanted this)

Psytronic
  • 6,043
  • 5
  • 37
  • 56
  • Essentially the same implmentation as Šime Vidas' answer, but using factory design pattern, which you could skip if you want, I just tend to use it for all most of my "classes" at the moment – Psytronic Mar 03 '11 at 14:09