Skip to content

Instantly share code, notes, and snippets.

@sorin-ionescu
Created February 25, 2012 01:42
Show Gist options
  • Select an option

  • Save sorin-ionescu/1905177 to your computer and use it in GitHub Desktop.

Select an option

Save sorin-ionescu/1905177 to your computer and use it in GitHub Desktop.
Solving the JavaScript inheritance clusterfuck.
var console = require('console');
/**
* The Problem:
*
* JavaScript librariers have developed many inheritance helpers,
* often classical, to avoid using the horrible Netscape Java
* marketer syntax to set up object inheritance chains.
*
* Prototypical inheritance should be dead simple, not convoluted.
*
* This is an example of how JavaScript inheritance should have been.
*
* First, a root object in the current Netscape marketer style,
* has to be defined for the example to work.
*/
function Prototype() {
this.init.apply(this, arguments);
}
Prototype.prototype = new Object();
Prototype.prototype.init = function() {
return this;
}
Prototype.prototype.clone = function() {
if (typeof Object.create !== 'function') {
function F() {}
F.prototype = this;
return new F();
} else {
return Object.create(this);
}
}
var Prototype = new Prototype();
/**
* Objective-C Syntax:
*
* Cocoa will be used as inspiration for a sane prototypical
* inheritance syntax.
*
* NSObject* foo = [[NSObject alloc] init];
*
* Since 'alloc' makes no sense in JavaScript, it will be
* replaced with 'clone'.
*/
var Animal = Prototype.clone();
Animal.init = function(name) {
/**
* This sanity check is necessary since 'init' methods
* can return anything.
*
* There is no 'super()' or, better yet, 'prototype()'
* to make this call easier.
*/
if (this === Prototype.init.apply(this, arguments)) {
this.name = name;
this.traits = {};
}
return this;
};
Animal.trait = function(name, value) {
if (arguments.length == 2) {
this.traits[name] = value;
return this;
} else {
return this.traits[name];
}
}
var Dog = Animal.clone()
Dog.init = function(name, age, weight) {
if (this === Animal.init.apply(this, arguments)) {
this.trait('age', age);
this.trait('weight', weight);
}
return this;
}
var husker = Dog.clone().init('Husker', 3, 15);
var buster = Dog.clone().init('Buster', 7, 20);
console.log('Husker', husker.traits);
console.log('Buster', buster.traits);
// The Good
console.log('Is Dog prototype of husker?', Dog.isPrototypeOf(husker)); // true
// The Bad
try {
console.log('Is husker instance of Dog?', husker instanceof Dog); // TypeError
} catch (e) {
console.error(e.message)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment