Last active
August 29, 2015 13:57
-
-
Save jakevdp/9613560 to your computer and use it in GitHub Desktop.
A simple Javascript inheritance pattern
This file contains 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
/********************************************************************** | |
I've been working with javascript for a bit, and I miss my | |
Python-style namespaces and class inheritance. Here's a little | |
pattern I came up with that allows me to do things (kind of) | |
the way I wish I could within javascript. I'd be curious if any | |
experienced JS users have comments or critiques. Thanks! | |
Edit - also see the second version (which I think is more clean) | |
below. | |
**********************************************************************/ | |
/* this is an anonymous function which defines the namespace myModule */ | |
!(function(){ | |
var myModule = {}; | |
/* subClass function implements simple inheritance */ | |
function subClass(base, derived){ | |
derived = (typeof derived === "function") ? derived : function(){}; | |
derived.prototype = new base(); | |
derived.prototype.constructor = derived; | |
derived.subClass = function(child){return subClass(derived, child);}; | |
return derived; | |
} | |
/* Create a Base class */ | |
myModule.Base = subClass(Object, Base); | |
function Base(){} | |
Base.prototype.foo = function(){ | |
console.log("call Base.foo()"); | |
}; | |
Base.prototype.bar = function(){ | |
console.log("call Base.bar()"); | |
}; | |
/* Create a Derived class with specialized bar() method */ | |
myModule.Derived = Base.subClass(Derived); | |
function Derived(x){ | |
console.log("initializing Derived(x = " + x + ")"); | |
} | |
Derived.prototype.bar = function(){ | |
console.log("call Derived.bar()"); | |
}; | |
/* put myModule in the global namespace */ | |
this.myModule = myModule; | |
})(); | |
/*--------------------------------------------------------------------------*/ | |
/* Everything below is depends on the module definition above. */ | |
/* We'll create an object and call both base and derived methods */ | |
var obj = new myModule.Derived(10); //--> "initializing Derived(x = 10)" | |
console.log(obj); //--> "Derived {...}" | |
obj.foo(); //--> "call Base.foo()" | |
obj.bar(); //--> "call Derived.bar()" |
This file contains 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
/********************************************************************** | |
Here's another version, which sets up a ``$sub`` method for a base | |
class named ``Class``. I think I like this pattern better... | |
**********************************************************************/ | |
// anonymous function to define ``Class`` | |
// we pass undefined explicitly in case it has been globally modified. | |
!function(undefined){ | |
var _noInit, Class = $sub(Object); | |
function $sub(Base, methods){ | |
function SubClass(){ | |
if(!_noInit && this.__init__) | |
return this.__init__.apply(this, arguments); | |
} | |
_noInit = true; SubClass.prototype = new Base; _noInit = false; | |
SubClass.prototype.constructor = SubClass; | |
for(m in methods){ SubClass.prototype[m] = methods[m]; } | |
SubClass.$sub = $sub.bind(this, SubClass); | |
return SubClass; | |
} | |
this.Class = Class; | |
}(); | |
var Base = Class.$sub({ | |
__init__: function(){console.log("constructing Base");}, | |
foo: function(){console.log("Base.foo");}, | |
bar: function(){console.log("Base.bar(" + this.x + ")");}, | |
x: 0, | |
}); | |
var Derived = Base.$sub({ | |
__init__: function(x){this.x = x;}, | |
foo: function(){console.log("Derived.foo(" + this.x + ")");}, | |
}); | |
obj = new Base(); // "constructing Base" | |
obj.foo(); // "Base.foo" | |
obj.bar(); // "Base.bar(0)" | |
obj = new Derived(4); | |
obj.foo(); // "Derived.foo(4)" | |
obj.bar(); // "Base.bar(4)" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment