0

I'm trying to do inheritance in javascript. First of all, looking on the web I found this

function A() {}
function B(){}
B.prototype = new A() ;
B.prototype.constructor = B ;

This works, however when I use the prototype property of B it doesn't work anymore ( http://jsfiddle.net/jeanluca/eQBUx/ )

function A() {}
A.prototype.bar = function(){ return 'A'; }

function B() {}
B.prototype.bar = function(){ return 'B'; }

I realize you could do

function B(){ this.bar = function(){ ... } } ;

But I think this is definitely slower than defining it using the prototype. So how could I do inheritance in the second situation ?

Thnx

Jeanluca Scaljeri
  • 26,343
  • 56
  • 205
  • 333

3 Answers3

2

Using this to assign properties breaks the prototype chain. It's very inefficient and you can't use it to get inheritance. So .. don't?

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • It doesn't alter the prototype chain, so how would it break it? – Bergi Aug 05 '13 at 11:44
  • 1
    You just answered your own question. – Halcyon Aug 05 '13 at 11:45
  • I usually use `this` for instance specific property values and prototype for default values of immutable property values and functions. Using `prototype.someArray` can cause unexpected results when doing something like `instance1.someArray.push("on all instances")` But would work perfectly fine to define default values like `Person.prototype.hands=2` Here is some detail when I'd use `this` or `prototype` http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Aug 05 '13 at 13:44
2

You're creating a property on a the prototype object which you completely replace afterwards. Do it the other way round, create the bar method on the new object. And don't use new!

function B() {}
// first create the prototype object
B.prototype = Object.create(A.prototype);
// then assign properties on it
B.prototype.bar = function(){ return 'B'; }
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

Here's your code:

function A() {}
A.prototype.bar = function(){ return 'A';}

function B() {}
B.prototype.bar = function(){ return 'B'; }
B.prototype = new A() ; // replaces B's "bar" with A's "bar

var b = new B ;
console.log(b.bar());

As you can see the problem is in your 6th line. You're first setting B.prototype.bar to a function in line 5 and then you immediately set B.prototype to new A in line 6 (effectively undoing what you did in line 5). The solution is to put line 6 before line 5:

function A() {}
A.prototype.bar = function(){ return 'A';}

function B() {}
B.prototype = new A() ; // now it will work
B.prototype.bar = function(){ return 'B'; }

var b = new B ;
console.log(b.bar());

See the demo for yourself: http://jsfiddle.net/eQBUx/1/

In addition I agree with Bergi: Stop using the new keyword.


Update: After reading your comment and understanding your problem in greater detail I would recommend you use my augment library for inheritance:

var A = Object.augment(function () {
    this.constructor = function () {};

    this.bar = function () {
        return "A";
    };
});

var B = A.augment(function (base) {
    this.constructor = function () {};

    this.bar = function () {
        return "B" + base.bar.call(this);
    };
});

var b = new B;

console.log(b.bar());

See the demo: http://jsfiddle.net/eQBUx/2/

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • Thnx, but I (and I didn't mentioned it, sorry) want to be able to call the overridden function, it will look like this: B.prototype.bar = function(){ return 'B' + this.$super(); }. Where $super probably does something Object.getPrototypeOf(this) – Jeanluca Scaljeri Aug 05 '13 at 12:15
  • @JeanlucaScaljeri Aadit's answer will work fine, I have posted another answer on inheritance and overriding here http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 Look under `Overriding functions` That answer is more an into to prototype in JS with code to fiddle with. – HMR Aug 05 '13 at 13:32
  • @HMR Cool. Personally I like my [`augment`](https://github.com/javascript/augment) library more. It provides inheritance, encapsulation, private state, base prototype access, singletons, the module pattern and a bunch of additional functional features all in just 17 lines of code. I even wrote a blog post on it: [Standardizing Harmony Classes](http://aaditmshah.github.io/standardizing-harmony-classes/) – Aadit M Shah Aug 05 '13 at 14:28