jquery mediator vs jquery

JavaScript performance comparison

Revision 2 of this test case created by Jason McAffee

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<div id="tests">
    <div id="htmlTest1">html test 1</div>
    <div id="findTest">
        <span class="test1">test1</span>
    </div>
</div>
<script>
Benchmark.prototype.setup = function() {
           //array of function names for functions that allow chaining.
        var allowedChainedFunctions = [
                'find',
                'not',
                'addClass',
                'removeClass',
                'toggleClass',
                'clone',
                'detached',
                'append',
                'appendTo',
                'prepend',
                'after',
                'removeAttr',
                'replaceWith',
                'remove',
                'show',
                'hide',
                'prev',
                'next',
                'toggle'
            ],
            //array of function names for functions that do not allow chaining.
            allowedNonChainedFunctions = [
                'extend',
                'hasClass',
                'outerHeight',
                'height',
                'data'
            ],
            allowedJQueryFunctionProperties = [
                'data',
                'ajax',
                'extend'
            ];
       
        //when our code base executes $(), they will actually be executing this function
        var jQueryMediator = function(selector, context){
            //execute the query function, using the same arguments passed into this function
            var $el = $.apply($, arguments);
            //var $el = $(selector, context); //no speed improvement.
            //wrap the $el result with a mediator object that only exposes the allowed jquery functions.
            return exposeFunctions($el);
        };
       
        //expose $.prop properties (data, extend, ajax, etc)
        for(var i=0; i < allowedJQueryFunctionProperties.length; ++i){
            var allowedFuncProp = allowedJQueryFunctionProperties[i];
            createAllowedJqueryFunction(allowedFuncProp);
        }
       
        function createAllowedJqueryFunction(allowedFuncProp){
            jQueryMediator[allowedFuncProp] = function(){
                return $[allowedFuncProp].apply($, arguments);    
            };    
        }
       
        //############################################# MediatedQueryObject ###################################
        function MediatedQueryObject($el){
            this._$el = $el;
        }
       
        MediatedQueryObject.prototype = {
            //gets or sets html
            html: function(newHtml){
                if(newHtml){ //chainable
                    var $result = this._$el.html(newHtml);
                    return exposeFunctions($result);//chained result shouldn't allow functions we dont allow
                }else{
                    return this._$el.html();
                }
            },
           
            attr: function(attr, value){
                if(typeof value != "undefined"){
                    var $result = this._$el.attr(attr, value);
                    return exposeFunctions($result);
                }
                return this._$el.attr(attr);
            },
           
            find2: function(selector){
                return exposeFunctions(this._$el.find(selector));        
            },
           
            changeClass: function(toClass, fromClass){
                this._$el.addClass(toClass).removeClass(fromClass);    
            },
           
            isChildOrSelf: function(parent, selector){
                parent = $(parent);
                while(parent.parent().length) {
                    if(parent.filter(selector).length === 0) {
                        parent = parent.parent();
                    }
                    else {
                        return true;
                    }
                }
                return false;    
            }  
        };
        createPrototypeForMediatedQueryObject();
       
        //assign functions to prototype
        function createPrototypeForMediatedQueryObject(){
            for(var i =0, allowedFunctionName; undefined !== (allowedFunctionName = allowedChainedFunctions[i]); ++i){
                createChainablePrototypeFunction(allowedFunctionName);
            }    
        }
       
        function createChainablePrototypeFunction(funcName){
            MediatedQueryObject.prototype[funcName] = function(){
                var $res = this._$el[funcName].apply(this._$el, arguments);
                return exposeFunctions($res); //chained results should only have functions we allow.    
            };
        }
       
        function exposeFunctions($el){
            var mediatedQueryObject = new MediatedQueryObject($el);
            return mediatedQueryObject;
        }
   
    var oldMediator = {
        find: function(element, selector){
            return $(element).find(selector)[0];
        },
        query: function(selector){
            return $(selector)[0];
        },
        html: function(el, newVal){
            if(newVal){
                $(el).html(newVal);
            }else{
                return $(el).html();
            }
        }
    };
    var jqueryInstance = $('#findTest');
    var mediatorInstance = jQueryMediator('#findTest');
    var oldMediatorEl = jqueryInstance[0];
};
</script>

Preparation code output

html test 1
test1

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
A. jquery instance
$('#findTest');
pending…
A. mediator instance
jQueryMediator('#findTest');
pending…
B. jquery find test
jqueryInstance.find('.test1');
pending…
B. mediator find (via array)
mediatorInstance.find('.test1');;
pending…
B. mediator find (explicitly defined)
mediatorInstance.find2('.test1');
pending…
B. old mediator find
oldMediator.find(oldMediatorEl, '.test1');
pending…
C. jquery multiple
$('#findTest').find('.test1').html();
 
pending…
C. mediator multiple
jQueryMediator('#findTest').find('.test1').html();
pending…
C. old mediator multiple
var el = oldMediator.query('#findTest');
var foundEl = oldMediator.find(el, '.test1');
oldMediator.html(foundEl);
 
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