jquery mediator vs jquery

JavaScript performance comparison

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'
    ],
      //array of function names for functions that do not allow chaining.
      allowedNonChainedFunctions = [
   
      ];
   
    //when our code base executes $(), they will actually be executing this function
    var jQueryMediator = function() {
      //execute the query function, using the same arguments passed into this function
      var $el = $.apply($, arguments);
      //wrap the $el result with a mediator object that only exposes the allowed jquery functions.
      return exposeFunctions($el);
    };
   
    function exposeFunctions($el) {
      var mediatedQueryObject = {
        _$el: $el //mainly for performance, as creating a bunch of closures will eat up memory and slow things down a bit, especially in .
      };
      exposeAllowedFunctions(mediatedQueryObject);
      exposeSpecialFunctions(mediatedQueryObject);
      return mediatedQueryObject;
    }
   
    //iterates over the allowed functions arrays and creates proxy functions.
    //when chained functions are used, proxy functions ensure that only allowed functions are accessible.
   
    function exposeAllowedFunctions(mediatedQueryObject) {
      for (var i = 0; i < allowedChainedFunctions.length; ++i) {
        var allowedFunctionName = allowedChainedFunctions[i];
        mediatedQueryObject[allowedFunctionName] = createMediatedFunctionClosureForChainable(allowedFunctionName);
      }
    }
   
    //since we are creating proxy functions within a loop, we need to scope the allowedFunctionName.
   
    function createMediatedFunctionClosureForChainable(allowedFunctionName) {
      return (function(funcName) { //todo: double check if this closure is truly needed. probably not..
        return function() {
          var $res = this._$el[funcName].apply(this._$el, arguments);
          return exposeFunctions($res); //chained results should only have functions we allow.
        };
      })(allowedFunctionName);
    }
   
    //$el already has a closure
   
    function exposeSpecialFunctions(mediatedQueryObject) {
   
      //gets or sets html
      mediatedQueryObject.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();
        }
      };
   
      mediatedQueryObject.find2 = function(selector){
        return exposeFunctions(this._$el.find(selector));        
      };
   
    }
   
    var jqueryInstance = $('#findTest');
    var mediatorInstance = jQueryMediator('#findTest');
};
</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 using closure
mediatorInstance.find('.test1');;
pending…
B. mediator find no closure
mediatorInstance.find2('.test1');
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