Skip to content

Instantly share code, notes, and snippets.

@protometa
Last active December 29, 2015 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save protometa/7671417 to your computer and use it in GitHub Desktop.
Save protometa/7671417 to your computer and use it in GitHub Desktop.
Uber simple ad hoc prototype inheritance
/*
uber simple ad hoc prototype inheritance
advantages:
- simple to use, construct inheritance on the fly or apply multiple inheritace
- perserve super methods with custom namespace
- flat prototype layer improves performance (no deep tree searches)
- prototyped methods save memory (even though each instance has it's own prototype object, each method is only defined once)
disadvantages:
- inheritance is static (once created, methods added to prototype won't propagate, and methods removed from instance won't reveal supers)
- potentially slower initialization
- instanceof is useless on a flat prototype
*/
/*
uber() method (working title)
augments an object as though it inherits from the given object
hierarchical inverse of extend(), similar to underscore's defaults()
allows option for preserving uber object's props with custom namespace
entirely flat, it doesn't link to a prototype, this is necessary for combinations of prototypes and multiple inheritance
*/
// Uberable prototype
// (if you're daring you could put on this right on Object.prototype)
Uberable = Object.create(Object.prototype,{
uber:{
enumerable: false,
value: function(obj,ns){
// for obj's own keys
for ( var key in obj ){ if( obj.hasOwnProperty(key) ){
// if not set in this
if( !this.hasOwnProperty(key) ){
// set from obj
this[key] = obj[key];
// otherwise if namespace is defined
} else if (ns != null ){
// set with namespace
this[ns+'_'+key] = obj[key];
}
}}
return this;
}
}
});
// handy chain initializer
Uber = function(obj){
return Object.create(Uberable).uber(obj);
};
// example prototypes for demo
A = Uber({
init: function () {
this.p = 'A';
return this;
},
methodA: function(){
this.p += 'A';
return this;
}
});
B = Uber({
init: function () {
this.superA_init();
this.p += 'B';
return this;
},
methodB: function(){
this.p += 'B';
return this;
}
}).uber(A,'superA'); // set to always inherit A (with namespace) because it depends on A's supers (see init)
C = Uber({
init: function () {
this.p = 'C';
return this;
},
methodC: function(){
this.p += 'C';
return this;
}
});
// combine (C inherits A)
CA = Uber(C).uber(A); // tip: start with new uber unless you want to uber the original prototype
// create
ca = Object.create(CA);
// init method is C's
console.assert( ca.init().p == 'C' );
// switch it up on the fly!
cb = Object.create( Uber(C).uber(B) ); // note: cb will also inherit from A since B is set to always do so
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment