Introduction
JavaScript does not support classes, it works with prototypes that allow for fully dynamic object creation but if one wants to have a more class-like behavior
a few tricks and work-arounds are needed.
The code was initially developed for use on the server side in Microsoft IIS (Jscript) and will also be adapted
for client-side use (Browsers) and use in node.js, in future releases.
Basics: classic JavaScript inheritance
The easy way of inheriting from base "classes", as shown in most JavaScript programming guides:
1: function MyBaseClass()
2: { MyBaseClass.iUsageCount++;
3: return this;
4: }
6: MyBaseClass.iUsageCount=0;
8: function MyDerivedClass()
9: {
10: }
12: MyDerivedClass.prototype=new MyBaseClass();
13:
15: var jDerivedInstance=new MyDerivedClass();
16: jDerivedInstance instanceof MyDerivedClass;
17: jDerivedInstance instanceof MyBaseClass;
18: jDerivedInstance instanceof Object;
Now let's have a look at the effects of this kind of inheritance:
- Pro: Easy to implement, easy to remember, and also easy to forget writing line 13.
- Pro: instanceof works as expected.
- Con: In line 12, the base class´ constructor is called and the usage count is set to 1, although we didn´t really want to create a "real" instance.
- Con: When not using line 13, instance.constructor would point to
MyBaseClass
, which is not correct. When using line 13, instance.constructor tells us the correct "class"
name, but instance.constructor.prototype does not tell us the base class any more. - Con: On instantiation of the derived class in line 15, the base constructor is not automatically called -- we would have to call it explicitly.
A first improvement
Now we try fixing the first few things on the classic inheritance code:
[...]
8: function MyDerivedClass()
9: { MyDerivedClass.__base__.call(this);
10: }
12: MyDerivedClass.prototype=Object.create(MyBaseClass);
13: MyDerivedClass.prototype.constructor=MyDerivedClass;
14: MyDerivedClass.prototype.__proto__=MyBaseClass.prototype;
15: MyDerivedClass.__base__=MyBaseClass;
17: var jDerivedInstance=new MyDerivedClass();
The changes in behaviour are now:
- Pro: In line 12,
Object.Create
gives the benefit of creating the needed base class instance without calling its constructor. - Con: But in IIS and IE<9.0,
Object.Create
is not available, so we will show an emulation function in the next edition of this article. - Pro: In line 14, we set the de-facto-standard property "
__proto__
", so we get a path to walk the inheritance chain, when we need it. We also set
a non-standard "__base__
" property directly on the constructor, so it will be easy to call the base constructor (line 9).
A surrogate constructor helps
Don´t forget that under IIS and IE<9.0, we don't have "Object.create()
". But we can use a so-called surrogate constructor to clone
the class by its prototype without its original constructor.
[...]
8: function Surrogate()
9: {
10: }
12: Surrogate.prototype=MyBaseClass.prototype;
13: MyDerivedClass.prototype=new Surrogate();
14: MyDerivedClass.prototype.constructor=MyDerivedClass;
15: MyDerivedClass.prototype.__proto__=MyBaseClass.prototype;
16: MyDerivedClass.__base__=MyBaseClass;
18: var jDerivedInstance=new MyDerivedClass();
We construct the Surrogate
class instead of the base class for use as the derived class' prototype, so the base constructor is not called, as with Object.create
, which we don´t have.
Next part: constructor chaining
In the next part of this article, we will look at how we can build a constructor chaining mechanism into our inheritance mechanism,
so base constructors will be called automatically/implicitly, as known from languages such as C++ or C#.
Your comments are welcome!
History
This is the original edition of the article.
has been working a total of 14 years as programmer and system developer, plus some years of working as network technician and application supporter. Also experienced modeling, optimizing and administering FireBird and SqlServer databases. Loathes MySql.
Works with C++, C++/CLI, C#, JavaScript, PHP, PSQL and TextPad.