Javascript 是否可以扩展EventTarget接口?

Javascript 是否可以扩展EventTarget接口?,javascript,javascript-events,addeventlistener,Javascript,Javascript Events,Addeventlistener,我正在寻找一个答案,如果这是可能的,甚至是一个好主意 通常,作为IE8和早期版本的修复,会使用类似的解决方法: var addEvent = function(obj, e, cb) { if(obj.attachEvent) { return obj.attachEvent('on' + e, cb); } else { obj.addEventListener(e, cb, false); return true; }

我正在寻找一个答案,如果这是可能的,甚至是一个好主意

通常,作为IE8和早期版本的修复,会使用类似的解决方法:

var addEvent = function(obj, e, cb) {
    if(obj.attachEvent) {
        return obj.attachEvent('on' + e, cb);
    } else {
        obj.addEventListener(e, cb, false);
        return true;
    }
}
然后程序员总是使用
addEvent
而不是
addEventListener

是否有任何方法或点可以创建一个
addEventListener
函数,当
attachEvent
未定义时,该函数将环绕该
attachEvent


我认为这有点棘手,因为EventTarget可以是DOM元素、文档、窗口或其他东西。

这取决于您要返回的距离。在IE8上,您可以扩展
Element.prototype
以向所有HTML元素添加功能,这至少是90%的工作量。我相当肯定你在IE6中做不到这一点(PrototypeJS不得不求助于扩展单个
元素
实例),我不记得IE7了。除非你瞄准东亚市场,否则你基本上可以忽略IE7和更早的版本

下面是一个如何做到这一点的示例:

(function() {
  // Functions for IE
  function stopPropagation() {
    this.cancelBubble = true;
  }
  function preventDefault() {
    this.returnValue = false;
  }
  function addEventUsingAttach(eventName, handler)
  {
    this.attachEvent("on" + eventName, function() {
      var e = window.event;
      e.stopPropagation = stopPropagation;
      e.preventDefault = preventDefault;
      handler.call(this, e);
    });
  }

  // Function to add `addEvent` to the given target object
  function extendIt(target)
  {
    if (target.addEventListener) {
      target.addEvent = Element.prototype.addEventListener;
    }
    else {
      target.addEvent = addEventUsingAttach;
    }
  }

  // Add it to `Element.prototype` if we have it
  if (typeof Element !== "undefined" &&
      typeof Element.prototype !== "undefined") {
    extendIt(Element.prototype);
  }

  // Add it to `window` and `document` (etc.)
  extendIt(window);
  extendIt(document);
})();
|

然后手动扩展其他事件目标,如
窗口
文档
(请参见上面代码列表的末尾)


原始答案:我最初误解了你的问题是关于添加
addEventListener
,特别是在IE8上,而事实上你的问题很明显不是关于添加那个,而是添加你自己的
addEvent
。我将这个答案留给其他读者:


这取决于你想走多远。在IE8上,您可以扩展
Element.prototype
以向其中添加
addEventListener
,页面上的所有HTML元素都将使用它(见下文)。不过,您添加的垫片无法支持捕获阶段,因为IE在本机支持
addEventListener
之前不支持它。我相当肯定你不能扩展
元素。prototype
在早期版本(IE7、IE6)上,PrototypeJS不得不退回到为旧版本的IE扩展特定元素上。但它在IE8中工作

扩展了
Element.prototype
,则必须手动扩展您提到的其他事件目标,但扩展
Element.prototype
完成了大部分工作

但是,如果您这样做并且包含第三方脚本,请注意,它们可能会假定在捕获阶段完成了
addeventlistener
的正确实现

下面是一个用于将
addEventListener
添加到IE8的基本垫片:

(function() {
  function stopPropagation() {
    this.cancelBubble = true;
  }
  function preventDefault() {
    this.returnValue = false;
  }
  if (typeof Element !== "undefined" &&
      typeof Element.prototype !== "undefined" &&
      !Element.prototype.addEventListener) {
    Element.prototype.addEventListener = function(eventName, handler, useCapture) {
      if (useCapture) {
        throw "Browser doesn't support capturing phase";
      }
      this.attachEvent("on" + eventName, function() {
        var e = window.event;
        e.stopPropagation = stopPropagation;
        e.preventDefault = preventDefault;
        handler.call(this, e);
      });
    };
  }
})();

|

通常,可以通过将函数附加到对象来将函数添加到对象

obj.addEventListener = function(/* args*/) { /* body */ }
或者将函数附加到对象构造函数的原型

EventTarget.prototype.addEventListener = function(/* args*/) { /* body */ }
使用前者,添加的函数只能在特定对象上调用,而使用后者,您可以在所有对象上调用该函数,这些对象是从该特定对象构造函数创建的

但是,

  • EventTargets是主机对象,因此是否可以将函数添加到此类对象取决于实现
  • EventTargets是主机对象,因此它取决于
    EventTarget.prototype是否实际存在,并且与本机对象具有相同的含义
  • 如果对象符合
    EventTarget
    接口,则它很可能已经具有
    addEventListener
    功能
  • 使用
    attachEvent
    附加的事件侦听器与使用
    addEventListener
    添加的事件侦听器具有不同的参数

最后,尝试使用JavaScript使一个具有蹩脚DOM的浏览器支持更高的标准兼容性是不可行的。

typeof EventTarget
“未定义的”
,即使在Chrome上,更不用说IE8了。实际上,T.J.我最初的意思是我可以包含类似于IE8脚本的内容(我完全赞成忽略之前的版本),然后正常使用
addEventListener
(不在IE8中捕获)。重点是避免使用命名独特的addEvent,而是使用基于标准的vanilla JS。