Created
February 25, 2012 01:42
-
-
Save sorin-ionescu/1905177 to your computer and use it in GitHub Desktop.
Solving the JavaScript inheritance clusterfuck.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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