Skip to content
Create a gist now

Instantly share code, notes, and snippets.

@jdalton /def.js secret forked from tobytailor/def.js

* def.js: Simple Ruby-style inheritance for JavaScript
* Copyright (c) 2010 Tobias Schneider
* This script is freely distributable under the terms of the MIT license.
(function(global) {
// used to defer setup of superclass and plugins
var deferred;
function addPlugins(plugins) {
augment(this.prototype, plugins);
return this;
// TODO: Ensure we fix IE to iterate over shadowed properties
// of those further down the prototype chain. There is also a
// bug in Safari 2 that will match the shadowed property and
// the one further down the prototype chain.
function augment(destination, source) {
for (var key in source) {
destination[key] = source[key];
// dummy subclass
function Subclass() { }
function def(klassName, context) {
// create class on given context (defaults to global object)
var Klass =
(context || global)[klassName] = function Klass() {
// called as a constructor
if (this != global) {
// allow the init method to return a different class/object
return this.init && this.init.apply(this, arguments);
// called as a method
// defer setup of superclass and plugins
deferred._super = Klass;
deferred._plugins = arguments[0] || { };
// add static helper method
Klass.addPlugins = addPlugins;
// called as function when not
// inheriting from a superclass
deferred = function(plugins) {
return Klass.addPlugins(plugins);
// valueOf is called to setup
// inheritance from a superclass
deferred.valueOf = function() {
var Superclass = deferred._super;
if (Superclass) {
Subclass.prototype = Superclass.prototype;
Klass.prototype = new Subclass;
return Klass.addPlugins(deferred._plugins);
return deferred;
// expose
global.def = def;
// Example
def ('Person') ({
'init': function(name) { = name;
'speak': function(text) {
alert(text || 'Hi, my name is ' +;
def ('Ninja') << Person ({
'kick': function() {
this.speak('I kick u!');
var ninjy = new Ninja('JDD');

May be add "super" attribute in constructor function?


@donnerjack13589 Sure thing, a lot can be done still.


Also, may be add plugins not only to prototype but to constructor too?


True. Ya, I don't know how far I want to take this.

I do a lot of this in FuseJS already.

I forked Tobias' gist primarily to clean it up and add comments explaining the coolness ;D


Clean up? Are you joking?
You've rewrited most of it. Only idea has survived


That's a very interesting approach @jdalton...


upz, congratulations to both @tobeytailor and @jdalton


This is really neat.

Two questions though:

How does the << syntax work?

Isn't superclass supposed to be a property of the instances you create? It's not coming through. If it's not meant to be there, how does method overloading work?



  1. I added a comment to the usage example explaining your first question.

  2. The superclass property is not on the subclass instance but on the subclass constructor.

    Method overloading and a magic super method isn't supported in this gist.


Regardless of the magic aspect, there is no way to do:
this.constructor.superclass.speak("super text");
from within Ninja's speak method, correct?

I just want to make sure I'm not doing something wrong :)


Look at this:

Sorry for comments on russian. But in this fork you can use your code.

May be add plugins not only to prototype?



git remote add donnerjack13589 git://
git pull donnerjack13589 master --commentignore=russian

If only :). Thanks for the info!


Tobias has set up a github repository for this now :D


Yep, will look tomorrow. But I don't like his super feature (it makes code bigger)


I've added my fixes here, also I've added multiple inheritance.
def ('a') << b()
def ('a') << c()

Also attributes/methods of superclass(and other parent classes) can be accessed from child.
def ('b') ({a:1})
def ('a') << b()
a.a === 1



I don't see any real inheritance being set up.
You are just porting methods from one object two another in a loop



Real inheritance can be set up only for __super_ class, cause js doesn't support real multiple inhertance.
But this methods will be in every object, created from this class.

And also you can do following:
def ('a') ({a : 1})
def ('a') ({b : 1})


Ok. So it's more like single inheritance + mixins




There is some prob in IE with

if (this != context)

as I mentioned on Twitter, it doesn't work in IE, so I replaced it with this.constructor == Klass as a quick fix. However, I found out that

if (context != this)

already works fine ;) Yet another crazy IE thing. Try to attach via debugger to IE (via standard Developer Tools of IE8, put breakpoint there, and you'll see this value confusion). So, I've changed this.constructor == Klass to if (context != this).

Also, I first used one < (as Ruby has), but not <<, but then found out that Chrome can't handle it, so I backed it to <<.



Right, the global object is notorious for it's weird matching in JScript:
alert(window == document); // true;
alert(document == window); // false

This is why I avoid that gotcha here;

I should have guessed it would carry over to this

alert((function(x){ return x})(this) == window); // true
alert((function(x){ { return this == x }; return })(this)); // false
alert((function(x){ { return x == this }; return })(this)); // true

Yeah, I knew about window == document (and vice-versa) issue in IE, but the second case was not so easy to catch at first glance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.