3

I don't understand why the following is happening:

I have the following code:

singleton = (function() {
    somePrivFunction = function() {
        return new B();
    }

    A = function() {};
    B = function() {};
    C = function() {};

    A.prototype.a = function() { console.log("a"); };

    B.prototype = A.prototype;
    B.constructor = B;
    B.prototype.b = function() { console.log("b"); };

    C.prototype = A.prototype;
    C.constructor = C;
    C.prototype.c = function() { console.log("c"); };

    return { 
        someFunction: function() { 
            return somePrivFunction(); 
        }
    }
})();

When I call singleton.someFunction() it returns me an instance of B. However all of the following work:

singleton.someFunction().b(); // Prints "b" 
singleton.someFunction().a(); // Prints "a" 
singleton.someFunction().c(); // Prints "c", but why? Shouldn't it be undefined?
William Barbosa
  • 4,936
  • 2
  • 19
  • 37
jaibatrik
  • 6,770
  • 9
  • 33
  • 62
  • You got the A, B,C inheritance all wrong. A Dog is an Animal but an Animal is not necessarily a Dog so setting one prototype to equal another is wrong. You can use Object.create instead. The following answer may help: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Nov 17 '14 at 16:11

1 Answers1

3

B.prototype has a reference to the same object as A.prototype (line 12). On line 16 you stored a reference of this same object to C.prototype. This means all three prototypes point to the same object, therefore all changes made to A.prototype, B.prototype or C.prototype will actually change the same object. At the end of your code, this object has three methods: a, b and c.

William Barbosa
  • 4,936
  • 2
  • 19
  • 37
  • Okay, I want B and C to inherit only A's methods, but not each others', is there a way to achieve that? – jaibatrik Nov 17 '14 at 11:13
  • 2
    @jaibatrik Do `B.prototype = new A();` – Dmitry Nov 17 '14 at 11:16
  • @Dmitry even though creating an instance of Parent to use as prototype of Child accidentally works here without problems I would not advice doing so, it's better to use Object.create – HMR Nov 17 '14 at 16:13
  • @HMR it is not *accidentally* works here. It is the only option for older browsers (IE8-). Besides `Object.create` with only 1 argument is equivalent to `new`. – Dmitry Nov 17 '14 at 19:45
  • @Dmitry I say accidentally works without problems. Try that again with mutable instance specific members on the Parent. Or certain constructor arguments that are not available when defining Child. So I'll repeat it again: it's better to use Object.create or it's polyfil (like inherits in google closure compiler that has existed for many many years) – HMR Nov 17 '14 at 23:07