function calls: direct vs apply vs call vs bind

JavaScript performance comparison

Revision 64 of this test case created by bob

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  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:
  var emptyy = {};
  var str = (function(){
      var id = performance.now()
      this[id] = f;
      var length = arguments.length;
      if (length === 1) var foo = this[id]();
  		////
  	else 
    { for (var k=0, m=length, args=[]; k<m; k++)
  	    args.push(arguments[k])
     var foo = f.apply(this, args);
    
    }
      delete this[id];
      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(' '))

};
</script>

Test runner

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

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
direct
that.f();
pending…
apply
f.apply(that);
pending…
call
f.call(that);
pending…
by string
that['f']();
pending…
direct (local)
f();
pending…
ugly
f.uglyCall(that)
pending…
ugly test
f.testUgly(that)
pending…
ugly process
that.process(f)
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.

0 Comments