Last active
April 3, 2023 20:37
-
-
Save CatTail/5548032 to your computer and use it in GitHub Desktop.
Javascript prototypal/classical/mixins
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
/* | |
* Introduces a typal object to make classical/prototypal patterns easier | |
* Plus some AOP sugar | |
* | |
* By Zachary Carter <zach@carter.name> | |
* MIT Licensed | |
* */ | |
var typal = (function () { | |
var create = Object.create || function (o) { function F(){}; F.prototype = o; return new F(); }; | |
var position = /^(before|after)/; | |
// basic method layering | |
// always returns original method's return value | |
function layerMethod(k, fun) { | |
var pos = k.match(position)[0], | |
key = k.replace(position, ''), | |
prop = this[key]; | |
if (pos === 'after') { | |
this[key] = function () { | |
var ret = prop.apply(this, arguments); | |
var args = [].slice.call(arguments); | |
args.splice(0, 0, ret); | |
fun.apply(this, args); | |
return ret; | |
}; | |
} else if (pos === 'before') { | |
this[key] = function () { | |
fun.apply(this, arguments); | |
var ret = prop.apply(this, arguments); | |
return ret; | |
}; | |
} | |
} | |
// mixes each argument's own properties into calling object, | |
// overwriting them or layering them. i.e. an object method 'meth' is | |
// layered by mixin methods 'beforemeth' or 'aftermeth' | |
function typal_mix() { | |
var self = this; | |
for(var i=0,o,k; i<arguments.length; i++) { | |
o=arguments[i]; | |
if (!o) continue; | |
if (Object.prototype.hasOwnProperty.call(o,'constructor')) | |
this.constructor = o.constructor; | |
if (Object.prototype.hasOwnProperty.call(o,'toString')) | |
this.toString = o.toString; | |
for(k in o) { | |
if (Object.prototype.hasOwnProperty.call(o, k)) { | |
if(k.match(position) && typeof this[k.replace(position, '')] === 'function') | |
layerMethod.call(this, k, o[k]); | |
else | |
this[k] = o[k]; | |
} | |
} | |
} | |
return this; | |
} | |
return { | |
// extend object with own typalperties of each argument | |
mix: typal_mix, | |
// sugar for object begetting and mixing | |
// - Object.create(typal).mix(etc, etc); | |
// + typal.beget(etc, etc); | |
beget: function typal_beget() { | |
return arguments.length ? typal_mix.apply(create(this), arguments) : create(this); | |
}, | |
// Creates a new Class function based on an object with a constructor method | |
construct: function typal_construct() { | |
var o = typal_mix.apply(create(this), arguments); | |
var constructor = o.constructor; | |
var Klass = o.constructor = function () { return constructor.apply(this, arguments); }; | |
Klass.prototype = o; | |
Klass.mix = typal_mix; // allow for easy singleton property extension | |
return Klass; | |
}, | |
// no op | |
constructor: function typal_constructor() { return this; } | |
}; | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, I found this 'cause i'm updated Zaach's excellent Jison library to emit typescript and incorporate PRs that I needed (c.f. ts-jison). I'm switching it to use templates (skeletons in Bison and am trying to grok all of the code (some notes).
So can you or @zaach explain how this typal library is used? I'm trying to understand its use in jison.