Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript inheritance

I know there is a lot of similar questions are tons of great answers to this. I tried to look at the classical inheritance methods, or those closure methods etc. Somehow I consider they are more or less "hack" methods to me, as it doesn't really what the javascript is designed to do. (Welcome anybody correct me if I am wrong). OK, as long as it works, I satisfy with the classical inheritance pattern like:

PARENTClass = function (basevar) { do something here; };
PARENTClass.prototype = { a: b, c: d}; // prototype is auto gen 

// Inheritance goes here
CHILDClass = function (childvar) { do something; };
CHILDClass.prototype = new PARENTClass(*1); // Actual inheritance to the prototype statement
// Instance
CHILDInstance = new CHILDClass(whatever);

Above is somehow, to my understanding the inheritance of JS. But one scenario I have no idea how to implement, is that what if I want to do some initializing DURING object creation (ie, within constructor), and the new object can be used right away.... My illustration on problem might not be too clear, so let me use the following C# Psuedo to explain what I want to do:

class PARENT {
    public PARENT (basevar) { ... }
}
class CHILD : PARENT {
    public CHILD (basevar) : PARENT (basevar) // constructor of child, and call parent constructor during construct.
    { ... }
}

For some reason (like init. UI elements), putting them in constructor seems the best way to do. Anyone have idea on how can I do it.

PS: in the *1, I have no idea what I should put there. PS2: The above situation I DID found the jquery.inherit library can do, I just wonder if not using library can achieve it. PS3: Or my understanding is wrong. Since javascript is not intended to mimick OOP (that's why i call it hack), what is the "CORRECT" logic to implement this.

like image 646
xandy Avatar asked May 31 '09 08:05

xandy


3 Answers

It is not a hack as such; JavaScript is a prototyped language, as defined by Wikipedia as where:

..classes are not present, and behavior reuse (known as inheritance in class-based languages) is performed via a process of cloning existing objects that serve as prototypes.

As it says, classes are not used in JavaScript; each object that you create is descended from the JavaScript Object; all objects in JavaScript have the prototype object, and all instances of objects you create 'inherit' methods and properties from their object's prototype object. Take a look at the MDC prototype object reference for more information.

As of this, when you call the line:

CHILDClass.prototype = new PARENTClass();

This allows the CHILDClass object to add methods and properties to its prototype object from the PARENTClass object, which creates an effect similar to the idea of inheritance present in class-based languages. Since the prototype object affects every instance created of that object, this allows the parent object's methods and properties to be present in every instance of your child object.

If you want to call your parent class's constructor in your child class's constructor, you use the JavaScript call function; this allows you to call the parent class's constructor in the context of the child class's constructor, therefore setting the newly prototyped properties in your child class to what they are set as in the parent class.

You also do not need to put anything where you have specified the *1, since that line is merely used to add the methods and properties to the child class's prototype object; however, bear in mind that it calls the parent class's constructor, so if there are any arguments that are fundamental in the operation of the parent class constructor, you should check that these are present so as to avoid JavaScript errors.

like image 186
Alex Rozanski Avatar answered Oct 24 '22 06:10

Alex Rozanski


You can manually invoke the parent constructor in the subclass constructor like this:

CHILDClass = function (basevar) {
  PARENTClass.call(this, basevar);
  // do something;
};

The trick here is using the call method, which allows you to invoke a method in the context of a different object. See the documentation of call for more details.

like image 26
Ayman Hourieh Avatar answered Oct 24 '22 08:10

Ayman Hourieh


JavaScript has no built-in support for inheritance hierarchies as type extension is supposed to be done via aggregation, ie adding desired functionality directly to the object itself or its prototype if the property is to be shared between instances.

Nevertheless, JS is powerful enough to make implementing other forms of object construction possible, including classical inheritance.

Given a clone function - which is enough to add 'true' prototypical inheritance, and not JavaScript's bastardization thereof - your exampe can be implemented like this:

function ParentClass(baseVar) {
    // do stuff
}

// don't overwrite the prototype object if you want to keep `constructor`
// see http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
ParentClass.prototype.a = 'b';
ParentClass.prototype.c = 'd';

function ChildClass(childVar) {
    // call the super constructor
    ParentClass.call(this, childVar);
}

// don't inherit from a ParentClass instance, but the actual prototype
ChildClass.prototype = clone(ParentClass.prototype);
ChildClass.prototype.e = 'f';

It's also possible to add some syntactic sugar for class-based inheritance - my own implementation can be found here.

The example from above would then read

var ParentClass = Class.extend({
    constructor: function(baseVar) {
        // do stuff
    },
    a: 'b',
    c: 'd'
});

var ChildClass = ParentClass.extend({
    e: 'f'
});
like image 37
Christoph Avatar answered Oct 24 '22 08:10

Christoph