function calls: direct vs apply vs call vs bind (v63)

Revision 63 of this benchmark created by bob on


Setup

var out=7, v=5;
  
  var f = function() {
      return out+this.v;
      };
  
  var that = {
    f: f,
  v:5
  };
  
  var bound = f.bind(that);
  
  var wrappedCall = function() {
      f.call(that);
      };
  var slice = Array.prototype.slice;
  Function.prototype.bind2 = function(_this) {
    var _self = this;
    var args = slice.call(arguments, 1);
    if (args.length === 0) {
      return function() {
        if (arguments.length === 0) return _self.call(_this);
        else if (arguments.length > 0) return _self.apply(_this, args);
      }
    }
  
    return function() {
      if (arguments.length === 0) return _self.apply(_this, args);
  
      var a2 = args.contact(slice.call(arguments));
      return _self.apply(_this, a2);
    }
  }
  
  var bound2 = f.bind2(that);
  
  var name = 'f';
  
  //////////////
  
  var emptyy = {};
  Function.prototype.testUgly = function(that){
  	if (!that) that = emptyy
      that.________ = this;
      var length = arguments.length;
      if (length === 1) var foo = that.________();
  	//else var foo = Function.prototype.call.apply(that.________, arguments);
      delete that.________;
      return foo;
  }
  
  //////////////
  
  
  //ugly, won't work on async:
  var emptyy = {};
  var str = (function(){
  	if (!that) that = emptyy
      that.________ = this;
      var length = arguments.length;
      if (length === 1) var foo = that.________();
  		////
  	else var foo = Function.prototype.call.apply(that.________, arguments);
      delete that.________;
      return foo;
  }).toString();
  str = str.slice(str.indexOf("{")+1, -1).split('////');
  strend = str.pop()
  
  for (var k=2, m=10; k<m; k++)
  {
  	var tmp = '\t\telse if (length === '+k+') var foo = that.________('
  	var tmpA = []
  	for (var l=1; l<k; l++) tmpA.push('arguments['+l+']')
  	str.push(tmp + tmpA.join(',') + ');\n')
  }
  
  str.push(strend)
  
  Function.prototype.uglyCall = new Function('that', str.join(' '))
  
  
  
  
  
  //ugly, won't work on async:
  var emptyy = {};
  var str = (function(){
  	if (!this) throw 'no fun'
      this.________ = f;
      var length = arguments.length;
      if (length === 1) var foo = this.________();
  		////
  	else var foo = Function.prototype.call.apply(this.________, arguments);
      delete this.________;
      return foo;
  }).toString();
  str = str.slice(str.indexOf("{")+1, -1).split('////');
  strend = str.pop()
  
  for (var k=2, m=10; k<m; k++)
  {
  	var tmp = '\t\telse if (length === '+k+') var foo = this.________('
  	var tmpA = []
  	for (var l=1; l<k; l++) tmpA.push('arguments['+l+']')
  	str.push(tmp + tmpA.join(',') + ');\n')
  }
  
  str.push(strend)
  that.process = new Function('f', str.join(' '))

Test runner

Ready to run.

Testing in
TestOps/sec
direct
that.f();
ready
apply
f.apply(that);
ready
call
f.call(that);
ready
by string
that['f']();
ready
direct (local)
f();
ready
ugly
f.uglyCall(that)
ready
ugly test
f.testUgly(that)
ready
ugly process
that.process(f)
ready

Revisions

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