UNPKG

2.84 kBJavaScriptView Raw
1/*
2 * Introduces a typal object to make classical/prototypal patterns easier
3 * Plus some AOP sugar
4 *
5 * By Zachary Carter <zach@carter.name>
6 * MIT Licensed
7 * */
8
9var typal = (function () {
10
11var create = Object.create || function (o) { function F(){} F.prototype = o; return new F(); };
12var position = /^(before|after)/;
13
14// basic method layering
15// always returns original method's return value
16function layerMethod(k, fun) {
17 var pos = k.match(position)[0],
18 key = k.replace(position, ''),
19 prop = this[key];
20
21 if (pos === 'after') {
22 this[key] = function () {
23 var ret = prop.apply(this, arguments);
24 var args = [].slice.call(arguments);
25 args.splice(0, 0, ret);
26 fun.apply(this, args);
27 return ret;
28 };
29 } else if (pos === 'before') {
30 this[key] = function () {
31 fun.apply(this, arguments);
32 var ret = prop.apply(this, arguments);
33 return ret;
34 };
35 }
36}
37
38// mixes each argument's own properties into calling object,
39// overwriting them or layering them. i.e. an object method 'meth' is
40// layered by mixin methods 'beforemeth' or 'aftermeth'
41function typal_mix() {
42 var self = this;
43 for(var i=0,o,k; i<arguments.length; i++) {
44 o=arguments[i];
45 if (!o) continue;
46 if (Object.prototype.hasOwnProperty.call(o,'constructor'))
47 this.constructor = o.constructor;
48 if (Object.prototype.hasOwnProperty.call(o,'toString'))
49 this.toString = o.toString;
50 for(k in o) {
51 if (Object.prototype.hasOwnProperty.call(o, k)) {
52 if(k.match(position) && typeof this[k.replace(position, '')] === 'function')
53 layerMethod.call(this, k, o[k]);
54 else
55 this[k] = o[k];
56 }
57 }
58 }
59 return this;
60}
61
62return {
63 // extend object with own typalperties of each argument
64 mix: typal_mix,
65
66 // sugar for object begetting and mixing
67 // - Object.create(typal).mix(etc, etc);
68 // + typal.beget(etc, etc);
69 beget: function typal_beget() {
70 return arguments.length ? typal_mix.apply(create(this), arguments) : create(this);
71 },
72
73 // Creates a new Class function based on an object with a constructor method
74 construct: function typal_construct() {
75 var o = typal_mix.apply(create(this), arguments);
76 var constructor = o.constructor;
77 var Klass = o.constructor = function () { return constructor.apply(this, arguments); };
78 Klass.prototype = o;
79 Klass.mix = typal_mix; // allow for easy singleton property extension
80 return Klass;
81 },
82
83 // no op
84 constructor: function typal_constructor() { return this; }
85};
86
87})();
88
89if (typeof exports !== 'undefined')
90 exports.typal = typal;