HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Custom event handler in Javascript

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptcustomhandlerevent

Problem

In my web projects I often need a simple way to trigger callbacks defined somewhere else. Leaving jQuery finally behind me, I was missing their simple event system and tried to create my own. I'd like to know if this is a good implementation since I am not that proficient with Javascript yet.

```
function Events ()
{
/**
* handlers for an event
*
* @var {object}
*/
this.stack = {}

/**
* on function.
* adds a callback to an event stack
*
* @param {string} event the event to subscribe to
* @param {function} callback the event callback to subscribe
*
* @return void
*/
this.on = function (event, callback)
{
// if there is no callback registered for this event yet,
// create an array for this event
if (! this.stack.hasOwnProperty(event)) {
this.stack[event] = []
}

// push the event callback to the handler stack
this.stack[event].push(callback)
}

/**
* off function.
* removes a callback from an event stack
*
* @param {string} event the event to unsubscribe from
* @param {function} callback the event callback to unsubscribe
*
* @return {bool} whether the callback was removed or not
*/
this.off = function (event, callback)
{
// if the event does not exist, return false
if (! event in this.stack) return false

// iterate over handlers, remove the callback in question
this.stack[event] = this.stack[event].filter(
function(item) {
if (item !== callback) {
return item
}
}
)

return true
}

/**
* trigger function.
* calls all registered callbacks for an event
*
* @param {string} eventName the event to trigger callbacks for
* @param {mixed} data optional data to hand over to the callbacks

Solution

Overall it looks pretty good. There are a couple of improvements.

-
Stylistically, JavaScript doesn't place the { character on a new line. You'll see it start on the same line separated by one space:

function Events() {
    // ...
}

if (condition) {
    // ...
} else if (condition) {
    // ...
} else {
    // ...
}


-
Since you are not using any function closure variables, there is no need to recreate the on and trigger methods each time the Events constructor function is called. Use the prototype property instead:

function Events() {
    this.stack = [];
}

Events.prototype = {
    stack: null,

    constructor: Event,

    on: function (event, callback) {
        // ...
    },

    off: function (event, callback) {
        // ...
    },

    trigger: function (event, data) {
        // ...
    }
};


-
You could remove the need for the new operator with a little constructor function trickery:

function Events() {
    if (!(this instanceof Events)) {
        return new Events();
    }

    this.stack = [];
}


This would allow you to generate a new Events object by calling Events():

Events().on("foo", function(event) {
    // ...
});


-
The word Events makes this seem like a collection of existing events. Really you've created an event dispatcher, and EventDispatcher feels like a better name.

Code Snippets

function Events() {
    // ...
}

if (condition) {
    // ...
} else if (condition) {
    // ...
} else {
    // ...
}
function Events() {
    this.stack = [];
}

Events.prototype = {
    stack: null,

    constructor: Event,

    on: function (event, callback) {
        // ...
    },

    off: function (event, callback) {
        // ...
    },

    trigger: function (event, data) {
        // ...
    }
};
function Events() {
    if (!(this instanceof Events)) {
        return new Events();
    }

    this.stack = [];
}
Events().on("foo", function(event) {
    // ...
});

Context

StackExchange Code Review Q#110889, answer score: 2

Revisions (0)

No revisions yet.