【发布时间】:2011-01-06 13:37:21
【问题描述】:
我目前正在为我正在进行的项目构建一个非常简单的 Observer 类。我已经成功实现了订阅、取消订阅和通知方法。使用“常规”函数(即:var f = function())时,一切都按预期工作。
但是,当我将匿名函数传递给 subscribe 方法然后尝试取消订阅传递“相同”匿名函数时,它(如预期的那样)不会从我的数组中删除该函数(毕竟它们是不同的)。
这是我的订阅和取消订阅方法:
this._subscribers = {};
subscribe: function(type, callback) {
if ( isUndefined(this._subscribers[type]) ) {
this._subscribers[type] = [];
}
this._subscribers[type].push(callback);
},
unsubscribe: function(type, callback) {
if ( this._subscribers[type] instanceof Array ) {
var index = this._subscribers[type].indexOf(callback);
if ( index >= 0 ) {
this._subscribers[type].splice(index, 1);
}
}
},
这是我正在测试的代码:
var o = new gaf.events.Observable();
o.subscribe('testEvent', function(event) { alert('Got It!'); });
o.notify('testEvent');
// Correct alerts 'Got It!'
o.unsubscribe('testEvent', function(event) { alert('Got It!'); });
o.notify('testEvent')
// Incorrectly alerts 'Got It!'
我知道我可以使用一个对象(即:_subscribers[event] = {}),然后当订阅某些东西时,我可以添加一个等于回调的新属性和等于回调的值。这将导致 Javascript 将回调转换为字符串。然后我可以使用该字符串查找它(前提是在 sub/unsub 中传递的方法完全相同)。
但是,这是一个移动项目,我对存储可能长达数百个字符的字符串非常谨慎,因为我们最终可能会有很多订阅者。
还有其他方法可以做到这一点吗?是否有任何 SMALL(小,甚至)散列库我可以用来散列函数的字符串值并将其用作属性?将回调的字符串值(以便我可以与它进行比较)存储在数组(而不是实际的回调)中并在其上使用eval() 会更好吗?
编辑
首先,感谢大家的回复!
关于“为什么还要传递匿名”函数的所有问题 -
确实没有理由不能使用命名函数。事实上,我同意每个人的观点,命名函数将是更好的解决方案。我只是在收集信息并寻找解决方案,这样我就可以构建一个尽可能最好地处理大多数场景的实现。
另一个原因是如果这个 Observable 类的用户(同事)向它传递了一个匿名函数然后取消订阅,会发生什么情况。该功能实际上不会被取消订阅,因此不会被清理。我反对孤立数据:)
也许我应该按原样提出另一个问题,是否可以测试回调是否是匿名的?我假设没有,但问一下也无妨。
【问题讨论】:
-
作为一个移动项目,我不认为你想通过复制匿名函数(一个订阅和一个取消订阅)来浪费空间。此外,您还需要散列库的开销(空间和性能)。散列库需要对函数进行“字符串化”,然后对其进行散列。 “stringify”操作需要正确地使用空格。这一切听起来让人头疼。我建议遵循将函数保存到变量或使用命名函数的最佳实践。
-
感谢您的评论!这就是为什么我不直接实现散列函数的原因。移动设备上该过程的开销和复杂性吓到我了。
标签: javascript dom-events anonymous-function mobile-website