我有一个页面,其中一些事件监听器附加到输入框和选择框。是否有一种方法可以找出哪些事件侦听器正在观察特定的DOM节点以及观察什么事件?

使用以下方法附加事件:

Prototype, Event.observe; 唐,addEventListener; 元素属性元素onclick


当前回答

Chrome, Firefox, Vivaldi和Safari在他们的开发人员工具控制台中支持getEventListeners(domElement)。

对于大多数调试目的,都可以使用这种方法。

下面是一个很好的使用它的参考: getEventListeners函数


Clifford Fajardo在评论中给出了高度投票的建议:

getEventListeners($0)将获得你在Chrome开发工具中关注的元素的事件监听器。

其他回答

Firefox开发工具现在可以做到这一点。事件是通过点击每个元素右侧的“ev”按钮来显示的,包括jQuery和DOM事件。

2022年更新:

在Chrome开发工具的元素面板中,有一个事件监听器选项卡,在那里你可以看到元素的监听器。

你也可以取消选择“祖宗”,这样它只显示该元素的监听器

1:原型。observe使用Element。addEventListener(参见源代码)

2:你可以覆盖元素。addEventListener用于记住添加的侦听器(方便的属性EventListenerList已从DOM3规范提案中删除)。在附加任何事件之前运行这段代码:

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    this._addEventListener(a,b,c);
    if(!this.eventListenerList) this.eventListenerList = {};
    if(!this.eventListenerList[a]) this.eventListenerList[a] = [];
    this.eventListenerList[a].push(b);
  };
})();

通过以下方式阅读所有活动:

var clicks = someElement.eventListenerList.click;
if(clicks) clicks.forEach(function(f) {
  alert("I listen to this function: "+f.toString());
});

不要忘记重写Element。removeEventListener从自定义的Element.eventListenerList中删除事件。

3:元素。Onclick属性在这里需要特别注意:

if(someElement.onclick)
  alert("I also listen tho this: "+someElement.onclick.toString());

4:不要忘记元素。Onclick内容属性:这是两个不同的东西:

someElement.onclick = someHandler; // IDL attribute
someElement.setAttribute("onclick","otherHandler(event)"); // content attribute

所以你也需要处理它:

var click = someElement.getAttribute("onclick");
if(click) alert("I even listen to this: "+click);

Visual Event bookmarklet(在最流行的回答中提到过)只窃取自定义库处理程序缓存:

It turns out that there is no standard method provided by the W3C recommended DOM interface to find out what event listeners are attached to a particular element. While this may appear to be an oversight, there was a proposal to include a property called eventListenerList to the level 3 DOM specification, but was unfortunately been removed in later drafts. As such we are forced to looked at the individual Javascript libraries, which typically maintain a cache of attached events (so they can later be removed and perform other useful abstractions). As such, in order for Visual Event to show events, it must be able to parse the event information out of a Javascript library.

元素覆盖可能是有问题的(即,因为有一些DOM特定的特性,如活动集合,不能在JS中编码),但它提供了eventListenerList原生支持,它在Chrome, Firefox和Opera中工作(在IE7中不工作)。

完全工作的解决方案基于Jan Turon的回答-行为类似于控制台的getEventListeners():

(有一个重复的小错误。反正也不怎么坏。)

(function() {
  Element.prototype._addEventListener = Element.prototype.addEventListener;
  Element.prototype.addEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._addEventListener(a,b,c);
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(!this.eventListenerList[a])
      this.eventListenerList[a] = [];
    //this.removeEventListener(a,b,c); // TODO - handle duplicates..
    this.eventListenerList[a].push({listener:b,useCapture:c});
  };

  Element.prototype.getEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined)
      return this.eventListenerList;
    return this.eventListenerList[a];
  };
  Element.prototype.clearEventListeners = function(a){
    if(!this.eventListenerList)
      this.eventListenerList = {};
    if(a==undefined){
      for(var x in (this.getEventListeners())) this.clearEventListeners(x);
        return;
    }
    var el = this.getEventListeners(a);
    if(el==undefined)
      return;
    for(var i = el.length - 1; i >= 0; --i) {
      var ev = el[i];
      this.removeEventListener(a, ev.listener, ev.useCapture);
    }
  };

  Element.prototype._removeEventListener = Element.prototype.removeEventListener;
  Element.prototype.removeEventListener = function(a,b,c) {
    if(c==undefined)
      c=false;
    this._removeEventListener(a,b,c);
      if(!this.eventListenerList)
        this.eventListenerList = {};
      if(!this.eventListenerList[a])
        this.eventListenerList[a] = [];

      // Find the event in the list
      for(var i=0;i<this.eventListenerList[a].length;i++){
          if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
              this.eventListenerList[a].splice(i, 1);
              break;
          }
      }
    if(this.eventListenerList[a].length==0)
      delete this.eventListenerList[a];
  };
})();

用法:

someElement.getEventListeners([name]) -返回事件监听器列表,如果设置了name则返回该事件的监听器数组

someElement.clearEventListeners([name]) -删除所有事件监听器,如果设置了name,则只删除该事件的监听器

更改这些函数将允许您记录添加的侦听器:

EventTarget.prototype.addEventListener
EventTarget.prototype.attachEvent
EventTarget.prototype.removeEventListener
EventTarget.prototype.detachEvent

朗读其余的听众

console.log(someElement.onclick);
console.log(someElement.getAttribute("onclick"));