1 min read

JavaScript 事件注册方法

出于一些历史遗留原因,JavaScript 的事件注册(绑定)方法有多种。

行内方法

这是最古老的方法,由 Netscape 引入,因为当时 Netscape 在浏览器市场的影响很大,IE 只能跟随,也因此这个方法最为通用,基本没有浏览器兼容性的问题。

它在 HTML 元素的事件属性中直接绑定:

<a href="http://www.zfanw.com/blog/" onclick="alert('hey it's me.');">....</a>

这种方法的好处是没有浏览器不兼容问题,但是我们将 JavaScript 代码混入了 HTML 中,这不合「行为与结构分离」的原则,会给我们带来很多麻烦。所以一般不会推荐这种用法。

在上例中,如果点击链接,则会有两个动作发生,一个是弹出对话框,一个是在当前标签页/窗口打开链接,两个动作的发生顺序也是由当时的 Netscape 决定的:

  1. 绑定的事件函数将先执行,在本例子中,会先弹出对话框;
  2. 打开链接,即 a 元素的默认动作

如果要阻止默认动作,则是在绑定的 JavaScript 事件处理函数中返回一个 false 值,

    <a href="http://www.zfanw.com/blog/" onclick="alert('hey it's me.');return false">....</a>

这样点击链接就只会弹出窗口,而不打开链接。

但显然不是所有的默认动作都允许 JavaScript 阻止,比如用户关闭页面而触发的 unload 动作,如果能被阻止,用户就连页面都关不掉,JavaScript 不会有这种蠢问题。

传统注册方法

所谓传统,是相对于现代浏览器的方法而言的。这种方法仍是由 Netscape 引入,IE 被迫跟随。

比如:

window.onload = doSomething;

但这种方法有个问题,就是同一个元素的同一个事件只能注册一个函数,如果你再为之注册一个函数,则后面的会覆盖掉前面一个。

另外,这种注册方法只支持事件冒泡,不支持捕获 – 这是事件执行顺序的两种阶段,具体可以看参考6中 W3 上的详述。

现代注册方法

W3C 很认真地推出新的事件注册方法想解决传统方法的问题。不可避免的是,Microsoft 又横出一脚,有自己的新的注册方法 – 直到 IE9 它才支持 W3C 的方法。于是这里要分为两种方法。

W3C DOM 事件注册方法

语法为:

target.addEventListener(type, listener[, useCapture]);

target 为绑定事件的对象,type 为事件的类型,比如 click、dbclick 等,listener 即绑定的事件处理函数,useCapture 为一个布尔值,指定事件处理是在哪个阶段发生,其默认值为 false,事件注册在冒泡阶段。

如果要绑定多个事件处理函数,则重复调用 addEventListener 方法则可,不会出现后来定义的覆盖前面的问题。

Microsoft 事件注册方法

在 IE9 之前,需要使用 IE 自有的事件注册方法 attachEvent,

object.attachEvent(event, pDisp) 

其中 event 为事件类型,类似于 W3C 定义的方法里 type 的意思,但是又有所区别,它是带有 「on」 的,比如 「onclick」,而 W3C 定义里是没有的。pDisp 指绑定的事件处理函数。

另外,attachEvent 方法有一个缺陷,它把 this 绑定到 window 对象上,而非调用它的对象上。

参考

  1. Early events handler
  2. Javascript – Traditional event registration model
  3. Javascript – Advanced event registration models
  4. element.addEventListener – Document Object Model (DOM) | MDN
  5. DOM events – Wikipedia, the free encyclopedia
  6. Document Object Model (DOM) Level 3 Events Specification
报告问题 修订

如果你有自建 https 代理的需求,欢迎尝试 Phantom,一键搭建,方便快捷。查看 demo