Backbone 触发事件
Backbone triggerEvents
我正在阅读 Backbone.js 事件模块的源代码,这段代码让我感到困惑:
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;
}
};
我想知道为什么要确定args.length
?为什么不这样写:
var triggerEvents = function(events, args) {
var ev, i = -1,
while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);
};
所以主要问题是:为什么要确定args.length
?为什么不用一个 while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);
代替所有 call
?
这是我的"educated guess"(不知道Backbone内部)
似乎每个 event
都有一个回调 属性,这是当 event
被触发时要调用的函数。例如 click
。
这个回调函数可以接受各种数量的参数。参数数量未知。这就是 args.length
发挥作用的地方。当您仅传递单个参数时,它将使用该单个参数调用回调函数。如果你用 2 调用它,它将传递 2 个参数,等等...
之所以有 callback.call()
和 callback.apply()
是因为 .call()
将参数传递给调用的函数 "one-by-one" 而 .apply()
将所有参数传递为单个数组。
关于 .call()
和 .apply()
之间的区别的很好的解释可以在这篇文章 http://hangar.runway7.net/javascript/difference-call-apply
中找到
PS:如果我对 Backbone 的猜测是错误的,请纠正我:)
更新
源代码 https://gist.github.com/badsyntax/4663217 中有注释,就在 triggerEvents
声明的上方。这就是你的答案。你可以试着找一些性能测试:)
// Optimized internal dispatch function for triggering events. Tries to
// keep the usual cases speedy (most Backbone events have 3 arguments).
更新 2
这个优化的原因是.call()
可以比.apply()
更快,因为.apply()
需要构造数组作为参数。 (并且调用 .call() 和 .apply 几乎总是比调用原始方法慢,原因很简单,因为要执行多一项操作)
我正在阅读 Backbone.js 事件模块的源代码,这段代码让我感到困惑:
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;
}
};
我想知道为什么要确定args.length
?为什么不这样写:
var triggerEvents = function(events, args) {
var ev, i = -1,
while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);
};
所以主要问题是:为什么要确定args.length
?为什么不用一个 while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);
代替所有 call
?
这是我的"educated guess"(不知道Backbone内部)
似乎每个 event
都有一个回调 属性,这是当 event
被触发时要调用的函数。例如 click
。
这个回调函数可以接受各种数量的参数。参数数量未知。这就是 args.length
发挥作用的地方。当您仅传递单个参数时,它将使用该单个参数调用回调函数。如果你用 2 调用它,它将传递 2 个参数,等等...
之所以有 callback.call()
和 callback.apply()
是因为 .call()
将参数传递给调用的函数 "one-by-one" 而 .apply()
将所有参数传递为单个数组。
关于 .call()
和 .apply()
之间的区别的很好的解释可以在这篇文章 http://hangar.runway7.net/javascript/difference-call-apply
PS:如果我对 Backbone 的猜测是错误的,请纠正我:)
更新
源代码 https://gist.github.com/badsyntax/4663217 中有注释,就在 triggerEvents
声明的上方。这就是你的答案。你可以试着找一些性能测试:)
// Optimized internal dispatch function for triggering events. Tries to
// keep the usual cases speedy (most Backbone events have 3 arguments).
更新 2
这个优化的原因是.call()
可以比.apply()
更快,因为.apply()
需要构造数组作为参数。 (并且调用 .call() 和 .apply 几乎总是比调用原始方法慢,原因很简单,因为要执行多一项操作)