L_K
L_K

Reputation: 2986

Backbone triggerEvents

I am reading Backbone.js sourcecode for Events module and this code got me confused:

var triggerEvents = function(events, args) {
  var ev, i = -1,
    l = events.length,
    a1 = args[0],
    a2 = args[1],
    a3 = args[2];
  switch (args.length) {
    case 0:
      while (++i < l)(ev = events[i]).callback.call(ev.ctx);
      return;
    case 1:
      while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1);
      return;
    case 2:
      while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1, a2);
      return;
    case 3:
      while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1, a2, a3);
      return;
    default:
      while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);
      return;
  }
};

I'm wondering why should we determine args.length? Why not just write like that:

var triggerEvents = function(events, args) {
    var ev, i = -1,
    while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);

};

So the main question is : Why should we determine args.length? Why not just use one while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args); to replace all call?

Upvotes: 1

Views: 112

Answers (1)

David Votrubec
David Votrubec

Reputation: 4156

This is my "educated guess" (without knowing Backbone internals) It seems that each event has a callback property, which is function to be called, when the event is triggered. Like click for example.

This callback function can take various number of arguments. Number of arguments is not known. That's where args.length kicks in. When you pass only single argument, it will call callback function with that single argument. If you call it with 2, it will pass 2 arguments, etc...

The reason why there is callback.call() and callback.apply() is because .call() passes the arguments to invoked function "one-by-one" whereas the .apply() passes all arguments as a single array.

Good explanation of difference between .call() and .apply() can be found in this article http://hangar.runway7.net/javascript/difference-call-apply

PS: Correct me if my guess about Backbone is wrong :)

UPDATE

There is comment in source code https://gist.github.com/badsyntax/4663217, just above the triggerEvents declaration. So that is your answer. You can try to find some perf tests :)

   // Optimized internal dispatch function for triggering events. Tries to
   // keep the usual cases speedy (most Backbone events have 3 arguments).

UPDATE 2

The reason for this optimization is that .call() can be faster than .apply(), because .apply() needs to construct the array as argument. (And calling .call() and .apply is almost always slower then calling the original method, simply because there is one more operation to perform)

Upvotes: 2

Related Questions