我经常需要让我自己的库通过回调订阅发出事件,在某些情况下,我更喜欢直接使用Javascript函数变量而不是某些第三方库或DOM来管理事件。我找到了两种策略,我不确定哪种策略更合适。
这些策略通过这个JSFiddle演示:http://jsfiddle.net/Q8pQT/2/
第一个策略是将每个订阅添加到一个函数数组,所以当我准备调用一个事件时,我可以迭代事件中的所有回调。
var fnactionidx = 0;
var fnarr = [];
function add2fnArray() {
fnarr.push(fnaction);
console.log("added to array", fnarr.length);
}
function fnaction() {
console.log("Hi.", ++fnactionidx);
}
function arraygo() {
// do internal stuff here first
fnactionidx = 0;
for (var i=0; i<fnarr.length; i++) {
fnarr[i]();
}
console.log("array complete!")
// do internal stuff here last
}
此示例中的订阅是使用简单的Array.push(fn)完成的。
第二个策略是定义一个初始函数,然后为每个订阅者用一个包含函数包装它。
function fnactionnested() {
console.log("nested complete!");
// do internal stuff here last
}
function nestfn(fn) {
var na = fnactionnested;
fnactionnested = function() {
fn();
na();
}
console.log("nested " + fn.toString());
}
function nestgo() {
// do internal stuff here first
fnactionidx = 0;
fnactionnested();
}
此示例中的订阅是使用nestfn完成的。请注意,我并不关心执行发生的顺序顺序,因为它是明确的;在第一个例子中,我可以使用Array.unshift。
我见过第二个推荐的更多。我的怀疑是,虽然第二个更像Javascript,因为它利用了Javascript灵活的函数作为函数式语言,它可能会引入更多的内存开销,因为你在包装器函数内部的包装器函数中有函数,等等,取决于有多少订户。
有关哪种方法更可取的想法?
请注意,我不想使用基于字符串的事件子系统,我只想区分这两种策略,或者是否有另一种回调策略可以执行与这两种策略非常相似的操作,而无需通过某些“全局”带有一些字符串键的事件系统。
答案 0 :(得分:0)
根据Knockout subscribable subscribe implementation(第35行)判断,似乎使用数组进行事件订阅已被相当受欢迎的先例使用。
还有一个重要的论据是基于数组来支持取消订阅这样的事件。使用数组可以做到这一点;功能包装几乎不可能。
另外,功能包装,当你用头包住它时,只是很奇怪,它可能更容易编写,但它不容易支持。另一方面,有些时候你别无选择,例如当另一个模块已经实现了一个事件,你的目标是在应用程序代码中的其他回调执行之前执行一些预处理。