apply vs call vs invoke (v11)

Revision 11 of this benchmark created on


Setup

function fn(a,b,c,d) {}
    var obj = {};
    var args=['a','b','c','d'];
    var fastInvoke = function(a) {
        switch(a.length) {
          case 1:  return a[0]();
          case 2:  return a[0](a[1]);
          case 3:  return a[0](a[1], a[2]);
          case 4:  return a[0](a[1], a[2], a[3]);
          case 5:  return a[0](a[1], a[2], a[3], a[4]);
          case 6:  return a[0](a[1], a[2], a[3], a[4], a[5]);
          case 7:  return a[0](a[1], a[2], a[3], a[4], a[5], a[6]);
          case 8:  return a[0](a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
          case 9:  return a[0](a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);
          case 10: return a[0](a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
          case 11: return a[0](a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10]);
          default: return a.shift().apply(null, a)
        }
    };

Test runner

Ready to run.

Testing in
TestOps/sec
apply
fn.apply(obj, ['a','b','c','d']);
ready
call
fn.call(obj, 'a', 'b', 'c', 'd');
ready
invoke
obj.fn = fn;
obj.fn('a','b','c','d');
delete obj.fn;
ready
apply (undef)
fn.apply(undefined, ['a','b','c','d']);
ready
call (undef)
fn.call(undefined, 'a', 'b', 'c', 'd');
ready
invoke (undef)
fn('a','b','c','d');
 
ready
Object.prototype.__method__
try {
  Object.prototype.__method__ = fn;
  obj.__method__('a','b','c','d');
} finally {
  Object.prototype.__method__ = undefined;
}
ready
{}.__method__
var proto = obj.__proto__, lastProto;
while (proto) {
  lastProto = proto;
  proto = proto.__proto__;
}
try {
  lastProto.__method__ = fn;
  obj.__method__('a','b','c','d');
} finally {
  lastProto.__method__ = undefined;
}
ready
fastInvoke
fastInvoke([fn, 'a','b','c','d']);
ready
fastInvoke without function wrap
switch(args.length) {
      case 0:  fn(); break;
      case 1:  fn(args[0]); break;
      case 2:  fn(args[0], args[1]); break;
      case 3:  fn(args[0], args[1], args[2]); break;
      case 4:  fn(args[0], args[1], args[2], args[3]); break;
      case 5:  fn(args[0], args[1], args[2], args[3], args[4]); break;
      case 6:  fn(args[0], args[1], args[2], args[3], args[4], args[5]); break;
      case 7:  fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break;
      case 8:  fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break;
      case 9: fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);break; 
      case 10: fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); break;
      default: fn.apply(null, args)
    }
ready

Revisions

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