apply vs call vs invoke (v10)

Revision 10 of this benchmark created by misko hevery on


Setup

function fn(a,b,c,d) {}
    var obj = {};
    
    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

Revisions

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