marrow.observatory vs jquery trigger events

JavaScript performance comparison

Revision 2 of this test case created by Anton Ignatov

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="https://gist.github.com/a-ignatov-parc/c5cff670ac12332fec2c/raw/22dc29647d407fce81278a51dd49f19f069c144f/core.observatory.js"></script>
<script>
var observatory2 = new Observatory2(),
    observatory = (function() {
                var regex = /\s+/,
                        eventMap = {
                                global: {}
                        },
                        rebuild = function() {
                                cache = {};

                                for (var namespace in eventMap) {
                                        // Проверяем принадлежит ли свойство объекту и не "заглушен" ли перебераемый неймспейс
                                        if (eventMap.hasOwnProperty(namespace) && !mutedEvents[namespace]) {
                                                var events = eventMap[namespace];

                                                for (var key in events) {
                                                        if (events.hasOwnProperty(key) && events[key] && events[key].length) {
                                                                if (namespace === 'global') {
                                                                        cache[key] = events[key];
                                                                } else {
                                                                        cache[key] || (cache[key] = []);
                                                                        cache[key] = cache[key].concat(events[key]);

                                                                        cache['.' + namespace] || (cache['.' + namespace] = []);
                                                                        cache['.' + namespace] = cache['.' + namespace].concat();

                                                                        cache[key + '.' + namespace] = events[key];
                                                                }
                                                        }
                                                }
                                        }
                                }
                        },
                        mutedEvents = {},
                        cache = {};

                return {
                        on: function(eventName, handler, context) {
                                // Создаем массив `events` в который парсится строка `eventName` на случай если в ней передано
                                // несколько событий или они переданы с лишними пустыми символами.
                                var events = eventName.split(regex),
                                        target = eventMap.global,
                                        parts;

                                // Проверяем было ли в строке `eventName` передано несколько событий.  
                                // Если да, то по очереди их навешиваем пробегаясь по созданному массиву `events`
                                if (events.length < 2) {
                                        eventName = events[0];
                                        parts = eventName.split('.');

                                        if (!eventName || !handler || typeof(handler) !== 'function') {
                                                return this;
                                        }

                                        if (!parts[parts.length - 1]) {
                                                parts.pop();
                                        }

                                        if (parts[0]) {
                                                if (parts.length > 1) {
                                                        target = eventMap[parts[1]] || (eventMap[parts[1]] = {});
                                                }
                                                target[parts[0]] || (target[parts[0]] = []);
                                                target[parts[0]].push({
                                                        h: handler,
                                                        c: context
                                                });
                                        }
                                        rebuild();
                                } else {
                                        for (var i = 0, length = events.length; i < length; i++) {
                                                arguments.callee.call(this, events[i], handler, context);
                                        }
                                }
                                return this;
                        },
                        off: function(eventName, handler, context) {
                                var parts = eventName.split('.'),
                                        parseList = function(list) {
                                                var newList = [];

                                                for (var i = 0, length = list.length; i < length; i++) {
                                                        var bundle = list[i];

                                                        if (!(bundle.h == handler && (context != null && bundle.c == context || context == null))) {
                                                                newList.push(bundle);
                                                        }
                                                }
                                                return newList;
                                        };

                                if (!parts[parts.length - 1]) {
                                        parts.pop();
                                }

                                for (var namespace in eventMap) {
                                        if (eventMap.hasOwnProperty(namespace) && (!parts[1] || parts[1] == namespace)) {
                                                var events = eventMap[namespace];

                                                if (typeof(handler) === 'function') {
                                                        if (events[parts[0]]) {
                                                                events[parts[0]] = parseList(events[parts[0]]);
                                                        } else {
                                                                for (var key in events) {
                                                                        if (events.hasOwnProperty(key) && events[key] && events[key].length) {
                                                                                events[key] = parseList(events[key]);
                                                                        }
                                                                }
                                                        }
                                                } else {
                                                        if (events[parts[0]]) {
                                                                delete events[parts[0]];
                                                        } else if (!parts[0] && parts[1]) {
                                                                delete eventMap[namespace];
                                                                delete mutedEvents[namespace];
                                                        }
                                                }
                                        }
                                }
                                rebuild();
                                return this;
                        },
                        trigger: function(eventName, params) {
                                var events = cache[eventName];

                                if (events) {
                                        for (var i = 0, length = events.length; i < length; i++) {
                                                var bundle = events[i],
                                                        handler = bundle.h,
                                                        context = bundle.c;

                                                if (typeof(handler) === 'function') {
                                                        if (context == null) {
                                                                context = this;
                                                        }
                                                        handler.apply(context, [eventName].concat(params));
                                                }
                                        }
                                }
                                return this;
                        },
                        mute: function(namespace) {
                                if (namespace != null && namespace != 'global' && !mutedEvents[namespace]) {
                                        mutedEvents[namespace] = true;
                                        rebuild();
                                }
                        },
                        unmute: function(namespace) {
                                if (namespace != null && namespace != 'global' && mutedEvents[namespace]) {
                                        delete mutedEvents[namespace];
                                        rebuild();
                                }
                        }
                };
        })();
</script>
<script>
observatory
    .on('test', function() {
        var a = 1+1;
    })
    .on('test.a1', function() {
        var b = 1+1;
    })
    .on('test.a2', function() {
        var c = 1+1;
    });

observatory2
    .on('test', function() {
        var a = 1+1;
    })
    .on('test.a1', function() {
        var b = 1+1;
    })
    .on('test.a2', function() {
        var c = 1+1;
    });

var jq = $({})
    .on('test', function() {
        var a = 1+1;
    })
    .on('test.a1', function() {
        var b = 1+1;
    })
    .on('test.a2', function() {
        var c = 1+1;
    })
   
    </script>

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
marrow.observatory v1.0.1
observatory.trigger('test');
pending…
jquery
jq.trigger('test');
pending…
marrow.observatory v1.1.0
observatory2.trigger('test');
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment