DOM元素的原型链最终追溯到EventTarget,因此所有DOM元素都能调用addEventListener等事件方法;其完整链条为HTMLDivElement→HTMLElement→Element→Node→EventTarget→Object.prototype。

在 JavaScript 中,DOM 元素(如 <div>、<code><button></button>)的原型链最终会向上追溯到 EventTarget,这是事件系统的基础接口。查找过程不是“手动搜索”,而是由 JS 引擎在调用方法(如 addEventListener)或访问属性时,按原型链自动向上查找。
DOM 元素的原型链结构
以 <div> 为例,其完整原型链大致为:
<ul>
<li>
<code>HTMLDivElement →
HTMLElement →Element →Node →EventTarget →Object.prototype这个链条是浏览器内置的,不可修改。所有 DOM 节点类型都继承自 Node,而 Node 直接继承自 EventTarget(注意:不是通过 Object.create(EventTarget.prototype),而是引擎级实现,但语义上等价)。
为什么 addEventListener 能在任意 DOM 元素上调用
因为该方法定义在 EventTarget.prototype 上,而所有 DOM 元素对象都能沿原型链访问它:
立即学习“Java免费学习笔记(深入)”;
-
document.createElement('div').addEventListener存在,尽管HTMLDivElement.prototype上没有该方法; - JS 引擎在访问
addEventListener时,依次检查:HTMLDivElement.prototype→HTMLElement.prototype→Element.prototype→Node.prototype→EventTarget.prototype,直到找到; - 一旦在
EventTarget.prototype找到,就绑定this为当前 DOM 元素并执行。
验证原型链中 EventTarget 的存在
可用 Object.getPrototypeOf() 逐层检查:
const div = document.createElement('div');
console.log(div instanceof EventTarget); // true
console.log(Object.getPrototypeOf(div) === HTMLDivElement.prototype); // true
console.log(Object.getPrototypeOf(Object.getPrototypeOf(div)) === HTMLElement.prototype); // true
// … 继续向上,最终:
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(div)))) === EventTarget.prototype); // true(在标准环境下,Node → EventTarget 是直接继承)
更简洁的方式是使用 div.constructor.name 链或 div.__proto__.__proto__...(不推荐生产环境),但核心逻辑一致:只要原型链中某一级的 prototype 是 EventTarget.prototype,就说明支持事件 API。
注意:EventTarget 是抽象基类,不能直接实例化
new EventTarget() 在多数浏览器中会报错(TypeError),因为它是规范中的接口,由浏览器内部实现供 DOM 类型复用。你无法扩展它来让普通对象拥有事件能力——除非用 class MyEmitter extends EventTarget(现代浏览器支持),这时新类的原型链也会包含 EventTarget.prototype。


















