Last active
December 29, 2015 12:39
-
-
Save protometa/7671417 to your computer and use it in GitHub Desktop.
Uber simple ad hoc prototype inheritance
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
/* | |
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