Lets imagine we are taking our express web application and isolating out the app routes and the socket events. The reason for this is simple: when a Web class extends the controller and event classes, they can share important pieces of information related to the web server such as a user session or login information. This will help us later on when implementing socket events for authorized users.
Here is the entire bit of code to get you going. It is simple, elegant, and for the most part completely readable as long as you have a bit of understanding in regards to the way prototypes in javascript work.
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
moduleKeywords = ['included', 'extended'] | |
class SuperClass | |
@include: (obj) -> | |
throw('include(obj) requires obj') unless obj | |
for key, value of obj.prototype when key not in moduleKeywords | |
@::[key] = value | |
included = obj.included | |
included.apply(this) if included | |
@ | |
class Controller | |
constructor: ()-> | |
@hasController = true | |
class Events | |
constructor: ()-> | |
@hasEvents = true | |
class Web extends SuperClass | |
@include Controller | |
@include Events | |
constructor: ()-> | |
Controller.call @ | |
Events.call @ | |
module.exports = Web |
Here is the compiled, fully javascript compliant version. As you can see, its a bit messy and definitely not as readable as the coffeescript version.
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
(function() { | |
var Controller, Events, SuperClass, Web, moduleKeywords, | |
__indexOf = [].indexOf || function(item) { | |
for (var i = 0, l = this.length; i < l; i++) { | |
if (i in this && this[i] === item) | |
return i; | |
} | |
return -1; | |
}, | |
__hasProp = {}.hasOwnProperty, | |
__extends = function(child, parent) { | |
for (var key in parent) { | |
if (__hasProp.call(parent, key)) | |
child[key] = parent[key]; | |
} | |
function ctor() { | |
this.constructor = child; | |
} | |
ctor.prototype = parent.prototype; | |
child.prototype = new ctor(); | |
child.__super__ = parent.prototype; | |
return child; | |
}; | |
moduleKeywords = ['included', 'extended']; | |
SuperClass = (function() { | |
function SuperClass() {} | |
SuperClass.include = function(obj) { | |
var included, key, value, _ref; | |
if (!obj) { | |
throw 'include(obj) requires obj'; | |
} | |
_ref = obj.prototype; | |
for (key in _ref) { | |
value = _ref[key]; | |
if (__indexOf.call(moduleKeywords, key) < 0) { | |
this.prototype[key] = value; | |
} | |
} | |
included = obj.included; | |
if (included) { | |
included.apply(this); | |
} | |
return this; | |
}; | |
return SuperClass; | |
})(); | |
Controller = (function() { | |
function Controller() { | |
this.hasController = true; | |
} | |
return Controller; | |
})(); | |
Events = (function() { | |
function Events() { | |
this.hasEvents = true; | |
} | |
Events.prototype.getEvents = function() { | |
return []; | |
}; | |
return Events; | |
})(); | |
Web = (function(_super) { | |
__extends(Web, _super); | |
Web.include(Controller); | |
Web.include(Events); | |
function Web() { | |
Controller.call(this); | |
Events.call(this); | |
} | |
return Web; | |
})(SuperClass); | |
module.exports = Web; | |
}).call(this); |
Happy coding.