YUI2.8自定义事件的一个小bug

发布于 2022-09-12 04:24:16 字数 2620 浏览 15 评论 0

YUI2.8的自定义事件如果添加了两个相同的侦听函数,在移除这些侦听函数时会有错误:

  1. var testEvent = new YAHOO.util.CustomEvent("testEvent");
  2. testEvent.subscribe(eventHandler);
  3. testEvent.subscribe(eventHandler);
  4. testEvent.unsubscribe(eventHandler);
  5. function eventHandler(){
  6.     alert("testEvent fire");
  7. }
  8. testEvent.fire();
  9. //只会显示一个"testEvent fire"

复制代码上面看似没问题,注册了两个相同的侦听函数,执行一次unsubscribe移除了一个,于是只剩一个侦听函数,但事实不是这样:

  1. var testEvent = new YAHOO.util.CustomEvent("testEvent");
  2. testEvent.subscribe(eventHandler);
  3. testEvent.subscribe(eventHandler);
  4. testEvent.subscribe(eventHandler);
  5. testEvent.subscribe(eventHandler);
  6. testEvent.unsubscribe(eventHandler);
  7. function eventHandler(){
  8.     alert("testEvent fire");
  9. }
  10. testEvent.fire();
  11. //只会显示两个"testEvent fire"

复制代码注册四个相同的侦听函数,执行了一次unsubscribe,却只剩下两个侦听函数有效。

原因
看unsubscribe的源码,在移除侦听函数时用了这样一个循环:

  1. for (var i=0, len=this.subscribers.length; i<len; ++i) {
  2.     var s = this.subscribers[i];
  3.     if (s && s.contains(fn, obj)) {
  4.         this._delete(i);
  5.         found = true;
  6.     }
  7. }
  8. ....
  9. _delete: function(index) {
  10.     var s = this.subscribers[index];
  11.     if (s) {
  12.         delete s.fn;
  13.         delete s.obj;
  14.     }
  15.    this.subscribers.splice(index, 1);
  16. }

复制代码问题出在,执行this.subscribers.splice(index,1)时数组长度变了,被删除的元素位置会被下一个元素位置顶替,而for循环里的i继续叠加,就会跳过漏检查这个位置的新元素。

修正方法
1.如果想一次unsubscribe移除所有相同的侦听函数,只需把for改成倒序遍历:

for (var i=this.subscribers.length-1; i>-1; i–)

这样在删除过程中数组元素个数和位置变化也不会导致漏检查。

2.如果想让unsubscribe一次只移除一个侦听函数,应该在for里找到符合条件的元素时跳出循环:

  1. for (var i=0, len=this.subscribers.length; i<;len; ++i) {
  2.     var s = this.subscribers[i];
  3.     if (s && s.contains(fn, obj)) {
  4.         this._delete(i);
  5.         found = true;
  6.         break;
  7.     }
  8. }

复制代码不知实际应用中会不会有同时注册两个相同的侦听函数的情况,有的话也是非常少的,所以此bug没什么威胁~

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文