SS = { setup: function(target, signals, slots){ function fireSetup(sigName){ return function(){ console.log('told to fire signal: ' + sigName, arguments); if(this._listeners[sigName]) for(var i = 0; i < this._listeners[sigName].length; i++){ this._listeners[sigName][i].apply(this, arguments); } } } var i; // setup helper methods for(i in this){ if(this.hasOwnProperty(i) && i !== 'setup'){ target[i] = this[i]; } } // setup signals for(i = 0; i < signals.length; i++){ target['_'+signals[i]] = fireSetup(signals[i]); target[signals[i]] = signals[i]; } console.log('target after signals', target); // setup slots for(i in slots){ target[i] = slots[i]; } return target; } ,connect: function(signal, slot){ if(typeof slot !== 'function') throw new Error('Slot must be a function'); if(typeof(this['_' + signal]) !== 'function') throw new Error('Signal not found: ' + signal); if(!this._listeners) this._listeners = {}; if(!this._listeners[signal]) this._listeners[signal] = []; this._listeners[signal].push(slot); } ,disconnect: function(){} ,emit: function(sig){} }; (function(exports){ //var signals = { // ready: function ready(){} // ,data: function data(){} // ,die: function die(){} //} var signals = ['READY', 'DATA', 'DIE']; // SLOTS var slots = { refresh: function refresh(data){ console.log('told to refresh'); } } function MyObj(){} MyObj.prototype = { doSomethingAsync: function(){ var self = this; setTimeout(function(){ self._DATA('behold! i am data!', 'so am i'); }, 1000); } }; SS.setup(MyObj.prototype, signals, slots); window.MyObj = MyObj; })(window); var my = new MyObj(); var myToo = new MyObj(); my.doSomethingAsync(); my.connect(my.DATA, myToo.refresh); console.log(my, MyObj, MyObj.prototype);