1

for a better structure I try to inherits on my classes in Javascript. Maybe my Approach is completely wrong or infeasible. Here is my Example Code:

function myMotherClass(value){
   this.MyValue = value
}

function myChildClass(value){
    this.prototype = new myMotherClass(value);
    this.alert = function(){
        alert(value);
    };
}

//myChildClass.prototype = new myMotherClass(1)

var myClass = new myChildClass(2);
myClass.alert();

here is my fiddle!

As you can see in my fiddle, if you use the commented line it is working fine.

if you can see the fiddle, i am trying to give the cunstructor value in myChildClass to the base "myMotherClass". But as you can see, there is a undefined output.

Thanks for your time and help in advance.

Ipad
  • 393
  • 1
  • 6
  • 22
  • Generally the kind of example posted by OP is achieved by using ``constructor`` and ``prototype chain`` Please refer [Classical Inheritance in JavaScript](http://www.crockford.com/javascript/inheritance.html). – Sarbbottam Jul 22 '14 at 06:00
  • See [Setting prototypes inside function constructor](http://stackoverflow.com/questions/16582608/setting-prototypes-inside-function-constructor) for an almost duplicate discussion. –  Jul 22 '14 at 06:06
  • @sarbbottam: Except that in that article, Crockford makes the classic mistake of calling the parent constructor when creating the child contructor's prototype, which is an anti-pattern and doesn't even work correctly with his example (`Parenizor` expects to receive a `value` argument, but `ZParenizor.inherits(Parenizor);` calls `Parenizor` without one [inside `inherits`]). – T.J. Crowder Jul 22 '14 at 07:04

1 Answers1

3

The reason it sort of seems to work with the commented out line is that myChildClass in that commented-out line is the function; but in the line inside the myChildClass constructor, this is not the function, it's the instance created by the new operator. The prototype property on functions is the object that will be assigned by the new operator to the new instances it creates, as their underlying prototype; there is no special meaning to the prototype property on instances (it doesn't, for instance, refer to the instance's underlying prototype).

The correct way to do this is this:

// Parent constructor
function myMotherClass(value){
   this.MyValue = value
}

// Child constructor
function myChildClass(value){
    // Chain to parent constructor, passing any necessary args
    myMotherClass.call(this, value);

    // Other child stuff -- see note below
    this.alert = function(){
        alert(value);
    };
}

// Set up inheritance by creating myChildClass's prototype
// property to be an object that is baked by myMotherClass's
// prototype object; do NOT *call* myMotherClass here, it's
// a common anti-pattern you'll see in a lot of examples
inherit(myMotherClass, myChildClass);

// Create an instance    
var myClass = new myChildClass(2);
myClass.alert();

...where inherit is:

function inherit(parent, child) {
    var temp;

    if (Object.create) {
        child.prototype = Object.create(parent.prototype);
    } else {
        temp = function() { };
        temp.prototype = parent.prototype;
        child.prototype = new temp();
    }
    child.prototype.constructor = child;
}

Note that with the way you're defining alert, this slightly strange behavior occurs:

var o = new myChildClass(42);
console.log(o.MyValue); // 42
o.alert();              // alerts "42"
o.MyValue = 67;
console.log(o.MyValue); // 67
o.alert();              // alerts "42" <== !!!

You can change how you define alert so it uses MyValue like this:

this.alert = function() {
    alert(this.MyValue);
};

...provided you always call it through the instance. (More on my blog: Mythical methods)

But if you're going to do that, you can move it to the prototype -- put this after the inherit call that sets up the chain:

myChildClass.prototype.alert = function(){
    alert(this.MyValue);
};

Here's that all put together:

// Parent constructor
function myMotherClass(value){
   this.MyValue = value
}

// Child constructor
function myChildClass(value){
    // Chain to parent constructor, passing any necessary args
    myMotherClass.call(this, value);

    // Other child stuff...
}

// Set up inheritance by creating myChildClass's prototype
// property to be an object that is baked by myMotherClass's
// prototype object; do NOT *call* myMotherClass here
inherit(myMotherClass, myChildClass);

// Add stuff to myChildClass's prototype property
myChildClass.prototype.alert = function(){
    alert(this.MyValue);
};

// Create an instance    
var myClass = new myChildClass(2);
myClass.alert();

If you're interested in classical inheritance in JavaScript, I have a handy helper script, Lineage, that makes the above simpler and adds a few useful features: http://code.google.com/p/lineagejs/

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Hej, thank you for this big and detailed answer, i will try your suggestions and mark it as answer as soon as i tried it :-) – Ipad Jul 22 '14 at 06:16
  • 1
    @Ipad: You're welcome. BTW, through an editing error I left a variable declared in `inherit` that it never uses, cleaned up above. :-) – T.J. Crowder Jul 22 '14 at 07:20