jQuery.proxy vs custom bind (plus mods) vs. Function.bind

Benchmark created by Rafael Gonzaque on


Preparation HTML

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>

Setup

var sum = function(x) {
      return this + x;
    }
    
    var bind = function(fn, context) {
      var slice = Array.prototype.slice,
        args = slice.call(arguments, 2);
    
      return Function.prototype.bind ? fn.bind(context, args) : function() {
        return fn.apply(
          context,
          args.concat(slice.call(arguments))
        )
      };
    };
    
    var bind2 = function( /* Function */ fn, /* * */ context) {
      if (Function.prototype.bind) {
        return fn.bind(context, Array.prototype.slice.call(arguments, 2));
      }
    
      return function() {
        return fn.apply(
          context,
          args.concat(Array.prototype.slice.call(arguments))
        )
      };
    };
    
    var bind3 = function( /* Function */ fn, /* * */ context) {
      return fn.bind ? fn.bind(context, Array.prototype.slice.call(arguments, 2)) : function() {
        return fn.apply(
          context,
          args.concat(Array.prototype.slice.call(arguments))
        )
      };
    };
    
    var bind4 = function( /* Function */ fn, /* * */ context) {
      var slice = Array.prototype.slice,
        args = slice.call(arguments, 2);
    
      return fn.bind ? fn.bind(context, args) : function() {
        return fn.apply(
          context || this,
          args.concat(slice.call(arguments))
        )
      };
    };
    
    var bind5 = function( /* Function */ fn, /* * */ context) {
      var slice = Array.prototype.slice,
        args = slice.call(arguments, 2);
    
      return function() {
        return fn.apply(
          context || this,
          args.concat(slice.call(arguments))
        )
      };
    };
    
    var bind6 = function( /* Function */ fn, /* * */ context) {
      // Return undefined instead of throwing an exception
      if (typeof fn != 'function') {
        return undefined;
      }
    
      var slice = Array.prototype.slice,
        args = slice.call(arguments, 2);
    
      return fn.bind ? fn.bind(context, args) : function() {
        return fn.apply(
          context || this,
          args.concat(slice.call(arguments))
        )
      };
    };

Test runner

Ready to run.

Testing in
TestOps/sec
jQuery.proxy
var jqSum = jQuery.proxy(sum, 5);
jqSum(6);
ready
Custom bind
var cbSum = bind(sum, 5);
cbSum(6);
ready
Native Bind
var nSum = sum.bind(5);
nSum(6);
ready
Custom bind 2 (No vars)
var cb2Sum = bind2(sum, 5);
cb2Sum(6);
ready
Custom bind 3 (Function.prototype.bind or native)
var cb3Sum = bind3(sum, 5);
cb3Sum(6);
ready
Custom bind 4 (.bind or native)
var cb4Sum = bind4(sum, 5);
cb4Sum(6);
ready
Custom bind 5 (Only native)
var cb5Sum = bind5(sum, 5);
cb5Sum(6);
ready
Custom bind 6 (Only native w/ callable check)
var cb6Sum = bind6(sum, 5);
cb6Sum(6);
ready
Underscore bind
var uSum = _.bind(sum, 5);
uSum(6);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Rafael Gonzaque on