The code below uses Javascript to create a base class, eventRaiser, that has the internals needed to allow clients to subscribe to events, and subclasses to raise these events. The idea is that other classes, like ThingWithEvent, will inherit from eventRaiser and expose the subscribe method, and fire off the raise method internally. The jQuery init function demonstrates this.
The way this is written, there’s nothing stopping a client from directly raising an event. In other words, adding er.raise("Y"); to the jQuery init function causes the Y event to be raised without difficulty.
Ideally I’d like to make it so that outside code, interacting with eventRaiser through some class that inherits from it, with can only subscribe to events, and not raise them.
In other words I’d like raise to be the equivalent of C# protected—visible only to itself, and classes that inherit from it.
Is there some slick ninja closure I should use to achieve this, or should I recognize that Javascript is not meant to incorporate OO Encapulation, rename raise to _raise to imply to client code that _raise is private and should not be invoked, and move on?
$(function() {
var er = new ThingWithEvent();
er.subscribe("X", function() { alert("Hello"); });
er.subscribe("X", function() { alert("World"); });
er.subscribe("Y", function() { alert("Not Called"); });
er.doSomething("X");
});
function eventRaiser() {
var events = {};
this.subscribe = function(key, func) {
if (!events[key])
events[key] = { name: key, funcs: [] };
events[key].funcs.push(func);
};
this.raise = function(key) {
if (!events[key]) return;
for (var i = 0; i < events[key].funcs.length; i++)
events[key].funcs[i]();
};
}
function ThingWithEvent() {
eventRaiser.call(this);
var self = this;
this.doSomething = function() {
alert("doing something");
self.raise("X");
}
}
function surrogate() { }
surrogate.prototype = eventRaiser;
ThingWithEvent.prototype = new surrogate();
ThingWithEvent.prototype.constructor = ThingWithEvent;
I hate answering my own question, let alone accepting my own answer, but it turns out this is not only possible, but insanely easy. The idea behind this code comes from Douglas Crockford’s JavaScript The Good Parts. The trick is to ditch constructors (neoclassical inheritance) altogether and use functional inheritance.
This code not only achieves public, protected, and private access levels, but it’s much cleaner, and easier to read IMO than inheriting constructors and swapping prototypes and constructors around. The only catch is that this code will be slightly slower since each object creation necessitates the creation of each of the object’s functions, instead of getting all that dumped in for free with a constructor’s prototype. So, if you need to create tens of thousands of objects in your web site then you might prefer a constructor. For…everyone else, this code is likely for you.