Skip to content

Instantly share code, notes, and snippets.

@CatTail
Last active April 3, 2023 20:37
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 CatTail/5548032 to your computer and use it in GitHub Desktop.
Save CatTail/5548032 to your computer and use it in GitHub Desktop.
Javascript prototypal/classical/mixins
/*
* 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; }
};
})();
@ericprud
Copy link

ericprud commented Apr 3, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment