1

I have an Object which called Rectangle :

    function Rectangle(x, y) {
            this.x = x;
            this.y = y ;
            this.surface = function(x, y) {
                return x*y;
            }
        }
Rectangle.prototype.couleur = "Rouge";

and I have two instances of this Object :

r1 = new Rectangle(3, 5);
r2 = new Rectangle(4, 7);

Then I declared a third instance :

r3 = new Rectangle(6, 7);

and I want this instance to have a unique method :

afficheCouleur = function() {
        return this.couleur;
    }

I tried as this :

r3.prototype.afficheCouleur = function() {
        return this.couleur;
    }

But I got this error :

[11:32:40.848] TypeError: r3.prototype is undefined @ file:///media/tpw/760F-F396/vv:24
Renaud is Not Bill Gates
  • 1,684
  • 34
  • 105
  • 191
  • Using prototypes means adding at class level, how can make that object level? – Shaik Mahaboob Basha Feb 12 '14 at 11:36
  • I think that color is instance specific and the function is not so maybe put color in the constructor function and the surface function on the prototype. You can't (or maybe you can with Object.getPrototypeOf or `__proto__` or r3.constructor.prototype but shouldnt) access an instance prototype and change it. more on constructor functions and prototype can be found here: http://stackoverflow.com/a/16063711/1641941 – HMR Feb 12 '14 at 13:51

3 Answers3

2

Just declare the method directly:

r3.afficheCouleur = function() {
    return this.couleur;
}

This happens because prototype is a property of constructors (functions) and r3 is an object.

Danilo Valente
  • 11,270
  • 8
  • 53
  • 67
1

If you do that you will end up with 2 Rectangles with a different implementation.

Create a second class that inherits from the first:

function Rectangle(x, y) {
    this.x = x;
    this.y = y ;
    this.surface = function(x, y) {
        return x*y;
    }
}
Rectangle.prototype.couleur = "Rouge";


function ColourRectangle(x, y) {
    Rectangle.apply(this, arguments);

    this.afficheCouleur = function() {
        return this.couleur;
    }
}
ColourRectangle.prototype = new Rectangle();
ColourRectangle.prototype.constructor = Rectangle;


var a = new Rectangle(1, 2);
console.log(a.y); //2
console.log(a.afficheCouleur);   //undef

var b = new ColourRectangle(3, 4);
console.log(b.y); //2
console.log(b.afficheCouleur()); // Rouge
Alex K.
  • 171,639
  • 30
  • 264
  • 288
  • It would be better if surface is on Rectangle.prototype and using Object.create instead of an instance of Parent (Rectangle) to set up prototype part of inheritance? – HMR Feb 12 '14 at 13:54
  • Yes, I just tend to avoid .create as its ie9+ only – Alex K. Feb 12 '14 at 14:10
  • It can cause problems because instance specific members of Parent end up in Child.prototype. When you don't run Parent constructor code in child (`Parent.call(this,args)`) you'll end up with Child instances sharing something that should not be shared. Another reason is that when you define Child.prototype, parameters are needed for Parent constructor may not be available and you'll have to fake them. goog.inherit has used the Object.create polyfil for many years it looks like this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Polyfill – HMR Feb 12 '14 at 14:18
1

Assuming that you might re factor your service function to use the Rectangle's x and y instead of passing them (why would you pass them if you want to know the Rectangle's surface?).

One problem you may have declaring service in the body like this is that it doesn't update x and y when you change x and y of your Rectangle instance. This because x and y are remembered in the closure scope.

You may end up with code like this:

function Rectangle(x, y) {
    this.x = x;
    this.y = y ;
    this.surface = function() {
        return x*y;
    }
}

var r = new Rectangle(5,5);
console.log(r.surface());//=25
r.y =500;
console.log(r.surface());//=25/
console.log(r.x*r.y);//=2500

you should return this.x * this.y in the surface method but since you are not using closures to simulate private members you may as well put the function on the prototype.

function Rectangle(x, y) {
    this.x = x;
    this.y = y ;
}
Rectangle.prototype.surface = function() {
    return this.x*this.y;
}

var r = new Rectangle(5,5);
console.log(r.surface());//=25
r.y =500;
console.log(r.surface());//=2500
console.log(r.x*r.y);//=2500

I know this doesn't answer your question but you are asking to add a method that will be shared among instances (prototype) uniquely on an instance. This can't be done as Danilo and Basha pointed out already.

The link posted in my comment to your question may help you understand better what prototype is, how the members there are used and what instance specific members are.

HMR
  • 37,593
  • 24
  • 91
  • 160