function calls: direct vs apply vs call vs bind

JavaScript performance comparison

Revision 60 of this test case created by Mark

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  function f() {
      return this;
  }
  var that = {
      f: f
  };
  var bound = f.bind(that);
  var that2 = Object.create(that);
  var that3 = {};
  var that4 = Object.create(that3);
  
  function bind( fn, scope ){
  	var args = ( arguments.length > 2 ) ? [].slice.call( arguments, 2 ) : []
  	  ;
  
  	return function(){
  		var argList = arguments.length ? args.slice() : args;
  
  		for( var i=0, l=arguments.length; i<l; i++ ){
  			argList.push( arguments[i] );
  		}
  
  		var numArgs = argList.length;
  
  		return (
  			( numArgs < 10 )
  				? scope
  					? (
  						  ( 0 === numArgs ) ? fn.call( scope )
  						: ( 1 === numArgs ) ? fn.call( scope, argList[0] )
  						: ( 2 === numArgs ) ? fn.call( scope, argList[0], argList[1] )
  						: ( 3 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2] )
  						: ( 4 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2], argList[3] )
  						: ( 5 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2], argList[3], argList[4] )
  						: ( 6 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2], argList[3], argList[4], argList[5] )
  						: ( 7 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2], argList[3], argList[4], argList[5], argList[6] )
  						: ( 8 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2], argList[3], argList[4], argList[5], argList[6], argList[7] )
  						: ( 9 === numArgs ) ? fn.call( scope, argList[0], argList[1], argList[2], argList[3], argList[4], argList[5], argList[6], argList[7], argList[8] )
  						: '' // can't get here
  					)
  					: (
  						  ( 0 === numArgs ) ? fn()
  						: ( 1 === numArgs ) ? fn( argList[0] )
  						: ( 2 === numArgs ) ? fn( argList[0], argList[1] )
  						: ( 3 === numArgs ) ? fn( argList[0], argList[1], argList[2] )
  						: ( 4 === numArgs ) ? fn( argList[0], argList[1], argList[2], argList[3] )
  						: ( 5 === numArgs ) ? fn( argList[0], argList[1], argList[2], argList[3], argList[4] )
  						: ( 6 === numArgs ) ? fn( argList[0], argList[1], argList[2], argList[3], argList[4], argList[5] )
  						: ( 7 === numArgs ) ? fn( argList[0], argList[1], argList[2], argList[3], argList[4], argList[5], argList[6] )
  						: ( 8 === numArgs ) ? fn( argList[0], argList[1], argList[2], argList[3], argList[4], argList[5], argList[6], argList[7] )
  						: ( 9 === numArgs ) ? fn( argList[0], argList[1], argList[2], argList[3], argList[4], argList[5], argList[6], argList[7], argList[8] )
  						: '' // can't get here
  					)
  				: fn.apply( scope, argList )
  		);
  	}
  }
  
  var bound2 = bind( f, that );
  var bound3 = bind( f );

};
</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…
bind
bound();
pending…
prototype
that2.f();
pending…
direct (dynamic property)
that3.f = f; that3.f();
pending…
prototype (dynamic property)
that3.f = f; that4.f();
pending…
fast bind
bound2();
pending…
bind, no scope
bound3();
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