Simple classical inheritance in JavaScript[source]

xml
<glacius:metadata>
    <title>Simple classical inheritance in JavaScript</title>
    <description>Classical inheritance implementation in JavaScript</description>
    <category>Legacy blog posts</category>
    <category>Programming</category>
    <category>JavaScript</category>
</glacius:metadata>
<glacius:macro name="legacy blargh banner">
    <properties>
        <originalUrl>https://tmont.com/blargh/2011/5/simple-classical-inheritance-in-javascript</originalUrl>
        <originalDate>2011-05-28T21:05:27.000Z</originalDate>
        <message>
            Note that this article was written long before things like "class" 
            were available in JavaScript.
        </message>
    </properties>
</glacius:macro>
<p>
  Inheritance in JavaScript is kind of tricky. JavaScript is object-oriented-ish, meaning most 
  things are objects. But it's also functional-ish, meaning that at times it behaves like a 
  functional language.
</p>
<p>
  My personal preference is that when I need to use inheritance, I use prototypal inheritance, 
  since that's what JavaScript was made for. Kind of. The prototype chain in JavaScript is a bit 
  wonky, and I shan't write about it here as it's been talked about by people far smarter than 
  myself. And I'm not going to pretend to understand every aspect of it.
</p>
<p>
  But on occasion, I find the desideratum is actually classical inheritance. There is a plethora 
  of "classical inheritance in JavaScript made E-Z" implementations out there, but they're 
  generally insanely complicated.
</p>
<p>Specifically, I wanted two things:</p>
<ol>
  <li><a href="https://en.wikipedia.org/wiki/Trait_(computer_programming)">Traits</a></li>
  <li>Call base/parent/super from an overridden method/constructor</li>
</ol>
<p>
  By traits, I mean I wanted to be able to import a collection of functions into multiple objects.
</p>
<p>
  Here's what I came up with, in 300 bytes (minified):
</p>
<glacius:code lang="javascript"><![CDATA[function extend(trait, func) {
	func.$super = func.$super || {};
	
	for (var i in trait.prototype) {
		func.prototype[i] = trait.prototype[i];
		if (typeof(trait.prototype[i]) === "function") {
			func.$super[i] = trait.prototype[i];
		}
	}
	
	if (!func.$parents) {
		func.$parents = [];
		func.$parent = trait;
	}
	func.$parents.push(trait);
	
	func.$override = function(funcToOverride, newImplementation) {
		func.$super[funcToOverride] = func.prototype[funcToOverride];
		func.prototype[funcToOverride] = newImplementation;
	};
}]]></glacius:code>
<p>
  This works in all browsers that I tested, which would be IE6+, Firefox, Chrome and Opera. 
  Here's an example illustrating the inheritance chain:
</p>
<glacius:code lang="javascript"><![CDATA[function BaseClass(name) {
	this.name = name || "world";
}
BaseClass.prototype.sayHello = function sayHelloBase(message) {
	console.log("Hello, " + this.name + (message ? ": " + message : "") + " from BaseClass");
}
function DerivedClass(name) {
	DerivedClass.$parent.call(this, name);
}
extend(BaseClass, DerivedClass);
DerivedClass.$override("sayHello", function sayHelloWithSalutation(message, salutation) {
	message = message || "";
	message += " from DerivedClass";
	
	if (!salutation) {
		DerivedClass.$super.sayHello.call(this, message);
	} else {
		console.log(salutation + ", " + this.name + (message ? ": " + message : ""));
	}
});
function SayHelloToBilly() {
	SayHelloToBilly.$parent.call(this, "billy");
}
extend(DerivedClass, SayHelloToBilly);
SayHelloToBilly.$override("sayHello", function sayHelloToBilly(message, salutation) {
	message = message || "";
	message += " from SayHelloToBilly";
	SayHelloToBilly.$super.sayHello.call(this, message, salutation);
});
console.group("BaseClass");
new BaseClass().sayHello();
console.groupEnd();
console.group("DerivedClass");
var derived = new DerivedClass("Dawg");
derived.sayHello();
derived.sayHello("a message", "Yo");
console.groupEnd();
console.group("SayHelloToBilly");
var billy = new SayHelloToBilly();
billy.sayHello("how are you", "Welcome");
billy.sayHello();
console.groupEnd();
console.group("SayHelloToBilly definition");
console.dir(SayHelloToBilly);
console.groupEnd();]]></glacius:code>
<p>And here's the output:</p>
<p class="text-center">
  <img glacius:src="blargh_extend.png" alt="extend output" />
</p>
  
<p>
  I'm not pretending this is a super excellent rendition of classical inheritance in 
  JavaScript: there are surely better ones out there (John Resig has one that I've used, 
  Dean Edwards also has one as part of base2). But if you need something quick, dirty and 
  lightweight, this should do nicely.
</p>