Most of the Javascript I write is object-oriented. While deciding what I would write about in my first posts, I realized that I would probably have to review Javascript OO techniques first. Any source code I included would be unintelligible to the uninitiated. In this post — and in the subsequent ones — I will review the Javascript inheritance techniques I use and explain why and when I use them.
This article assumes that you, the reader, have a background in object-oriented programming techniques. If not, please check out the primer at Wikipedia.
Javascript is a prototypal language. This means that objects inherit from other objects and that object classes describe their common behavior via prototypes. Prototypes are akin to member declarations in classical inheritance. For example, if a Javascript object, A, has a method, doSomething(), in its prototype, then another object of the same “class”, say object B, also has a method, doSomething(), in its prototype. (Notice I quoted the word, “class”. More on that below.)
If objects A and B inherit from another object, C, then they both inherit any members on C’s prototype. This is because the prototypes are “chained”. At run-time, when a member is referenced on an object, the prototype chain is scanned. For example, if C has a method, doSomethingElse(), then calling A.doSomethingElse() is valid.
Like some other languages, Javascript uses the familiar new operator. However, surprisingly, there is no formal method to declare a class. Instead of using it on a class, the new operator is used on a function. (In fact, it can be used on any function!) The new operator simply interprets the function as an object constructor and pulls the function’s prototype into the new object’s prototype chain.
A prototype chain is similar in nature to a classical inheritance heirarchy. Here is a simple example:
var Pet = function () { }; // using object literal (shorthand) notation: Pet.prototype = { eat: function () { /* do something here */ }, sleep: function () { /* do something here */ }, play: function () { /* do something here */ } }; var Cat = function () { }; Cat.prototype = new Pet(); // chain prototype Cat.prototype.technicalName = 'feline'; Cat.prototype.scratch = function () { /* do something here */ }; Cat.prototype.meow = function () { return 20; /* decibels */ }; var SiameseCat = function () { }; SiameseCat.prototype = new Cat(); // chain prototype SiameseCat.prototype.breedName = 'Siamese'; SiameseCat.prototype.meow = function () { // call ancestor method return Cat.prototype.meow.call(this) * 3; }; var myCat = new SiameseCat(); myCat.play(); // inherited from Pet myCat.scratch(); // inherited from Cat myCat.meow(); // from SiameseCat |
However, since Javascript is so flexible, it lends itself to several variations and alternatives. This is where the fun begins…
As a matter of fact, `new` can be used not just with any function, but with any object that implements internal [[Construct]] method; It just happens that all function objects are being given this [[Construct]] when created, and it is [[Construct]] that’s being invoked when `new` is called 🙂
Interesting. Do you have any examples of objects that implement the internal [[Construct]] method?
Also, I imagine that JScript is different. True?
I have never seen non-function objects with [[Construct]]. Was simply pointing out the inner workings of ECMAScript, for anyone who’s interested 🙂
It’s of course possible that some host objects would implement something like this.