Reputation: 2986
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
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