Javascript 基于回调和基于事件的事件处理系统之间的区别是什么?

Javascript 基于回调和基于事件的事件处理系统之间的区别是什么?,javascript,javascript-events,Javascript,Javascript Events,我正在开发一个跨浏览器事件处理系统。我请一些开发人员检查我的代码。一位开发人员说,我的实现基于回调,而不是真实事件。有什么区别 为了您的方便,我在下面提供了我的实现的源代码。到目前为止,我还没有发现任何问题。它适用于我测试过的所有浏览器 我很抱歉对这个问题的糟糕描述,我不熟悉纯事件部分 var evento = (function (window) { var win = window , doc = win.document , _handlers = {} , a

我正在开发一个跨浏览器事件处理系统。我请一些开发人员检查我的代码。一位开发人员说,我的实现基于回调,而不是真实事件。有什么区别

为了您的方便,我在下面提供了我的实现的源代码。到目前为止,我还没有发现任何问题。它适用于我测试过的所有浏览器

我很抱歉对这个问题的糟糕描述,我不熟悉纯事件部分

var evento = (function (window) {
  var win = window
    , doc = win.document
    , _handlers = {}
    , addEvent
    , removeEvent
    , triggerEvent;

  addEvent = (function () {
    if (typeof doc.addEventListener === "function") {
      return function (el, evt, fn) {
        el.addEventListener(evt, fn, false);
        _handlers[el] = _handlers[el] || {};
        _handlers[el][evt] = _handlers[el][evt] || [];
        _handlers[el][evt].push(fn);

      };
    } else if (typeof doc.attachEvent === "function") {
      return function (el, evt, fn) {
        el.attachEvent(evt, fn);
        _handlers[el] = _handlers[el] || {};
        _handlers[el][evt] = _handlers[el][evt] || [];
        _handlers[el][evt].push(fn);
      };
    } else {
      return function (el, evt, fn) {
        el["on" + evt] = fn;
        _handlers[el] = _handlers[el] || {};
        _handlers[el][evt] = _handlers[el][evt] || [];
        _handlers[el][evt].push(fn);
      };
    }
  }());

  // removeEvent
  removeEvent = (function () {
    if (typeof doc.removeEventListener === "function") {
      return function (el, evt, fn) {
        el.removeEventListener(evt, fn, false);
        Helio.each(_handlers[el][evt], function (fun) {
          if (fun === fn) {
            _handlers[el] = _handlers[el] || {};
            _handlers[el][evt] = _handlers[el][evt] || [];
            _handlers[el][evt][_handlers[el][evt].indexOf(fun)] = undefined;
          }
        });

      };
    } else if (typeof doc.detachEvent === "function") {
      return function (el, evt, fn) {
        el.detachEvent(evt, fn);
        Helio.each(_handlers[el][evt], function (fun) {
          if (fun === fn) {
            _handlers[el] = _handlers[el] || {};
            _handlers[el][evt] = _handlers[el][evt] || [];
            _handlers[el][evt][_handlers[el][evt].indexOf(fun)] = undefined;
          }
        });
      };
    } else {
      return function (el, evt, fn) {
        el["on" + evt] = undefined;
        Helio.each(_handlers[el][evt], function (fun) {
          if (fun === fn) {
            _handlers[el] = _handlers[el] || {};
            _handlers[el][evt] = _handlers[el][evt] || [];
            _handlers[el][evt][_handlers[el][evt].indexOf(fun)] = undefined;
          }
        });
      };
    }
  }());

  // triggerEvent
  triggerEvent = function (el, evt) {
    _handlers[el] = _handlers[el] || {};
    _handlers[el][evt] = _handlers[el][evt] || [];

    for (var _i = 0, _l = _handlers[el][evt].length; _i < _l; _i += 1) {
      _handlers[el][evt][_i]();
    }
  };

  return {
    add: addEvent,
    remove: removeEvent,
    trigger: triggerEvent,
    _handlers: _handlers
  };
}(this));
var evento=(函数(窗口){
var win=窗口
,doc=win.document
,_handlers={}
,附录
,removeEvent
,触发事件;
addEvent=(函数(){
if(doc.addEventListener的类型==“函数”){
返回函数(el、evt、fn){
el.addEventListener(evt、fn、false);
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
_处理器[el][evt].推送(fn);
};
}else if(doc.attachEvent的类型==“函数”){
返回函数(el、evt、fn){
el.附件(evt,fn);
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
_处理器[el][evt].推送(fn);
};
}否则{
返回函数(el、evt、fn){
el[“on”+evt]=fn;
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
_处理器[el][evt].推送(fn);
};
}
}());
//移除
removeEvent=(函数(){
if(doc.removeEventListener的类型==“函数”){
返回函数(el、evt、fn){
el.removeEventListener(evt、fn、false);
Helio.each(_handlers[el][evt],函数(fun){
如果(乐趣===fn){
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
_handlers[el][evt][[u handlers[el][evt].indexOf(fun)]=未定义;
}
});
};
}else if(doc.detachEvent的类型==“函数”){
返回函数(el、evt、fn){
el.事件(evt,fn);
Helio.each(_handlers[el][evt],函数(fun){
如果(乐趣===fn){
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
_handlers[el][evt][[u handlers[el][evt].indexOf(fun)]=未定义;
}
});
};
}否则{
返回函数(el、evt、fn){
el[“on”+evt]=未定义;
Helio.each(_handlers[el][evt],函数(fun){
如果(乐趣===fn){
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
_handlers[el][evt][[u handlers[el][evt].indexOf(fun)]=未定义;
}
});
};
}
}());
//触发事件
triggerEvent=功能(el、evt){
_handlers[el]=_handlers[el]|{};
_handlers[el][evt]=_handlers[el][evt]| | |[];
对于(var _i=0,_l=_handlers[el][evt].length;_i<_l;_i+=1){
_处理程序[el][evt][u i]();
}
};
返回{
add:addEvent,
移除:移除通风,
触发器:triggerEvent,
_处理程序:\u处理程序
};
}(本);;

我非常关心您的系统是否基于回调、事件或lambda演算。对于您在这里公开的部分,它似乎写得相当好,并承诺会做得很好(尽管我对您如何处理
removeent()
;)感到好奇)

然而,我对你们的实施有几点看法:

  • 每次添加事件处理程序时,无需检查执行的浏览器
我感到惊讶的是,每次打电话给他们时,都有很多人接受检查房产是否存在的做法。NoOne将在函数调用中间用IE交换FF(并且任何愚蠢到足以定义<代码>文档的人。AdvEntDistListabue/Case>除实际ECMA-5替换之外的属性应该被鞭笞至死,如果你问我),那么检查你启动的平台是什么,然后完成它,比如:

if (doc.addEventListener) {
    addEvent  = // ...
    freeEvent = // ...
}
else if (doc.attachEvent) {
    addEvent  =  // ...
    freeEvent =  // ...
}
/* etc. */
  • 您提供了一个统一的接口来附加处理程序,但是,根据您的代码将在哪个浏览器上执行,实际的处理程序的行为将有所不同
例如,在IE8-中,事件目标的可用方式与ECMA-5约定中的不同

如果希望提供真正的跨浏览器界面,则应为事件处理程序提供统一的执行上下文。 这可能包括一个“取消”功能,可以转换为以下内容:

cancel = function (e) { e.returnValue = false; }; // IE8-
cancel = function (e) { e.preventDefault();    }; // ECMA-5
您还应该将
this
恢复到IE8-下的目标对象,并统一
target
event.target
语义

如果你真的想善待程序员,你也可以解决一些奇怪的问题,比如

  • 加载事件未在IE8中触发-当映像已缓存时
  • 极其复杂的鼠标滚轮报告系统
可能还有其他一些

出于我自己的目的,我这样做的方式是围绕实际的处理程序生成一个包装器,它可以处理所有平台的特殊性,并在调用实际的用户代码之前建立一个一致的执行上下文


最后一句话:除了它的美,我不太确定它是否仍然需要支持Netscape4风格的活动。但这是一个信念的问题,所以…

我不知道那个开发人员在说什么。你问了吗?事件系统可以是响应特定操作并在该操作发生时导致某些行为的任何系统。回调只是一个函数,可以传递给另一个函数,以便以后调用。请注意,在IE
typeof doc.attachEvent中,attachEvent
返回
object
(在实现的地方),因此这些代码叉永远不会被执行。一些宿主对象返回