0

Consider the following code:

function rectangle(x, y) {
    this.width = x;
    this.height = y;
    this.calcArea = function() {
        return (this.width * this.height);
    };
}

The rectangle object has two properties (width and height) and one method (calcArea).

I wish to add another property to the rectangle object: area. I will do this through the prototype method, like so:

rectangle.prototype.area = function () {return this.calcArea();}

Imagine now that we create a new instance of rectangle: var r = new rectangle(2,3); Unfortunately, area is a method. To retrieve the correct value you must call r.area();

Since area should be (semantically, at least) a property and not a method, is there a way to directly assign the result of calcArea() to the r.area property?

If I change the prototype to this:

rectangle.prototype.area = function () {this.area = this.calcArea();}

I have to call r.area() once, and then all subsequent calls to r.area will be a number, as desired. It's not bad, but it's not perfect. So is there a better way?

Andy F
  • 1,517
  • 2
  • 20
  • 35
  • 1
    Something already accounted here: http://stackoverflow.com/questions/812961/javascript-getters-and-setters-for-dummies But you will need to forget IE. – Alvin Wong Nov 19 '12 at 14:35
  • 1
    Why not just add this.area= x*y; in the rectangle(x, y) function? – alemangui Nov 19 '12 at 14:37

3 Answers3

2

The area of the rectangle is calculated from other properties, that change from rectangle to rectangle. Area, therefore, does not belong to the prototype but to each instance. There is no point in having a property in the prototype that will be obscured by each and every instance of Rectangle anyway. The calculation can belong to the prototype though, because it is the same for each rectangle.

In order to get the value you have to calculate it at least once, just as you said. You can perform this calculation in the constructor of your Rectangle, but it is better to leave the method in the prototype as it does not need to be duplicated.

function Rectangle(x, y) {
    this.width = x;
    this.height = y;
    this.area = this.calculateArea();
}

Rectangle.prototype.calculateArea = function(){
    return this.width * this.height;
}

Keep in mind though that this value wont be updated if you change your rectangle dimensions after it is created. For this reason, I'd always calculate it on demand as it is safer, unless this property is called often and performance is an issue.

Martin Vézina
  • 319
  • 2
  • 8
1
function rectangle(x, y) {
    this.width = x;
    this.height = y;
    this.calcArea = function() {
        return (this.width * this.height);
    };
    this.area = this.calcArea();
}

You can do this way, but this.area will not update if you modify width or height. But you can check this : https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty It may help you.

Magus
  • 14,796
  • 3
  • 36
  • 51
1

Why not calculate it in the constructor?

function rectangle(x, y) {
    this.width = x;
    this.height = y;
    this.area = x*y;
    ..
}

Now the problem, it wont be updated if you update width or height. In that case use this.

function rectangle(x, y) {
    this.width = x;
    this.height = y;
    this.area = x*y;
    this.updateWidth = function(w){
        this.width = w;
        this.area = this.width*this.height;
    }
    this.updateHeight = function(h){
        this.height = h;
        this.area = this.width*this.height;
    }
}
Shiplu Mokaddim
  • 56,364
  • 17
  • 141
  • 187