Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Super.js : micro JS Class
/*!
* Copyright (c) 2011 Laurent Villeneuve mazesoul at gmail dot com
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
var Klass = (function(){
var slice = function( a ){
var s = [].slice
return s.apply(a, s.call(arguments,1))
}
function ocreate(proto){
function F(){};
F.prototype = proto;
proto.constructor = F;
return new F;
}
return function Klass( base , protoextra ){
if( arguments.length === 1 ){ // Single param signature
if( typeof base === 'function' ) protoextra = {}
else{
protoextra = base;
base = function(){}
}
}
var k, p;
function Cstr(){
if( 'init' in this ) this.init.apply(this, slice(arguments));
}
Cstr.prototype = p = ocreate( base.prototype )
// Add protoextra and bind constructor manually
for(k in protoextra)
p[k] = protoextra[k]
p.constructor = Cstr
// _super: Awesome meta-magik. Closing over the prototype chain
p._super = function(method, args){
// Catching second run of this._super, meaning this._super was already assigned base.prototype._super.
// It implies that the method is located at least 2 levels up in the normal prototype chain.
// Invoking _super through _super effectively recurse up the _super chain.
if( base.prototype[method] === this[method] )
return this._super.apply(this,['_super'].concat( slice(arguments)))
// In case the method in base.prototype calls this._super we need to make it point to base
this._super = base.prototype._super;
// Invoke the intended method
var result = base.prototype[method].apply(this, slice(arguments,1))
// Resume to normal _super
delete this._super;
return result
}
// Add extend to the new constructor to allow Cstr.extend( { protoextra } )
Cstr.extend = function( protoextra ){ return Klass( Cstr, protoextra ); }
return Cstr;
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment