# 事件-EventTarget

​事件的本质是程序各个组成部分之间的一种通信方式,也是异步编程的一种实现。

DOM 的事件操作都定义在 EventTarget 接口,所有的节点对象都部署了这个接口,其他一些需要事件通信的浏览器内置对象(比如 XMLHttpRequest)也部署了这个接口。

EventTarget 是一个 DOM 接口,由可以接收事件、并且可以创建侦听器的对象实现。

Element,document 和 window 是最常见的 event targets ,但是其他对象也可以作为 event targets,比如 XMLHttpRequest,AudioNode,AudioContext 等等。

# 基本使用

  • 构造函数
const eventTarget = new EventTarget()
  • 方法

  • EventTarget.addEventListener(type,listener[,options]) 在 EventTarget 上注册特定事件类型的事件处理程序。

  • EventTarget.removeEventListener(type, listener[,options]) EventTarget 中删除事件侦听器。

  • EventTarget.dispatchEvent(event) 将事件分派到此 EventTarget。

const eventTarget = new EventTarget();
eventTarget.addEventListener("hello", (e) => {
  console.log(e.target === eventTarget); // true
  console.log(e.detail) // world
});
setTimeout(()=>{
  const helloEvent = new CustomEvent("hello", { detail: "world" }
  eventTarget.dispatchEvent(helloEvent));
},1000)

# EventTarget 的简单实现

var EventTarget = function() {
  this.listeners = {};
};

EventTarget.prototype.listeners = null;
EventTarget.prototype.addEventListener = function(type, callback) {
  if(!(type in this.listeners)) {
    this.listeners[type] = [];
  }
  this.listeners[type].push(callback);
};

EventTarget.prototype.removeEventListener = function(type, callback) {
  if(!(type in this.listeners)) {
    return;
  }
  var stack = this.listeners[type];
  for(var i = 0, l = stack.length; i < l; i++) {
    if(stack[i] === callback){
      stack.splice(i, 1);
      return this.removeEventListener(type, callback);
    }
  }
};

EventTarget.prototype.dispatchEvent = function(event) {
  if(!(event.type in this.listeners)) {
    return;
  }
  var stack = this.listeners[event.type];
  event.target = this;
  for(var i = 0, l = stack.length; i < l; i++) {
      stack[i].call(this, event);
  }
};