angular.bind vs native

Benchmark created by Karl Seamon on


Setup

function isFunction(value){return typeof value === 'function';}
    
    function bind(self, fn) {
      var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
      if (isFunction(fn) && !(fn instanceof RegExp)) {
        return curryArgs.length
          ? function() {
              return arguments.length
                ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
                : fn.apply(self, curryArgs);
            }
          : function() {
              return arguments.length
                ? fn.apply(self, arguments)
                : fn.call(self);
            };
      } else {
        // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
        return fn;
      }
    }
    
    var fnProtoBind = Function.prototype.bind;
    function bind2(self, fn) {
      var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
      if (isFunction(fn) && !(fn instanceof RegExp)) {
        if (fnProtoBind && fn.bind === fnProtoBind) {
          curryArgs.unshift(self);
          return fnProtoBind.apply(fn, curryArgs);
        }
        return curryArgs.length
          ? function() {
              return arguments.length
                ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
                : fn.apply(self, curryArgs);
            }
          : function() {
              return arguments.length
                ? fn.apply(self, arguments)
                : fn.call(self);
            };
      } else {
        // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
        return fn;
      }
    }
    
    
    function bind3(self, fn) {
      var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
      if (isFunction(fn) && !(fn instanceof RegExp)) {
        return curryArgs.length
          ? function() {
              return arguments.length
                ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
                : fn.apply(self, curryArgs);
            }
          : function() {
              return fn.apply(self, arguments);
            };
      } else {
        // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
        return fn;
      }
    }
    
    
    var func = function() {},
        obj = {};
    
    
    var funcOld = bind(obj, func),
        funcNew = bind2(obj, func),
        funcTweaked = bind3(obj, func);

Test runner

Ready to run.

Testing in
TestOps/sec
angular.bind no args
funcOld()
ready
angular.bind with native bind no args
funcNew()
ready
angular.bind 1 arg
funcOld('arg')
ready
angular.bind with native bind 1 arg
funcNew('arg')
ready
tweaked angular.bind no args
funcTweaked()
ready
tweaked angular.bind 1 arg
funcTweaked('arg')
ready
angular.bind random args
var args = [], num;
while((num = Math.random) > .5) args.push(num);
funcOld.apply(null, args);
ready
angular.bind with native bind random args
var args = [], num;
while((num = Math.random) > .5) args.push(num);
funcNew.apply(null, args);
ready
tweaked angular.bind with random args
var args = [], num;
while((num = Math.random) > .5) args.push(num);
funcTweaked.apply(null, args);
ready

Revisions

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

  • Revision 1: published by Karl Seamon on