说说 JavaScript 事件流之内存和性能

来源:互联网 发布:创业软件 俞青 编辑:程序博客网 时间:2024/06/06 05:53

在 JavaScript 中,添加到页面的事件处理程序的数量会直接影响到页面的整体运行性能。有这些原因:

  1. 每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。
  2. 事先指定的事件处理程序会增加 DOM 的访问次数,从而延迟整个页面的交互就绪时间。

1 事件委托

事件委托利用事件冒泡,可以只指定一个事件处理程序来管理某一类型的所有事件:

<body><ul id="myLinks">    <li id="goSomewhere">Go somewhere</li>    <li id="doSomething">Do something</li>    <li id="sayHi">Say hi</li></ul><script type="text/javascript" src="EventUtil.js"></script><script type="text/javascript">    var list = document.getElementById("myLinks");    EventUtil.addHandler(list, "click", function (event) {        event = EventUtil.getEvent(event);        var target = EventUtil.getTarget(event);        switch (target.id) {            case "doSomething":                document.title = "I changed the document's title";                break;            case "goSomewhere":                location.href = "http://www.163.com";                break;            case "sayHi":                console.log("hi");                break;        }    })</script></body>

使用事件委托技术,只需在 DOM 树中尽量高的层次上添加一个事件处理程序即可,是不是很方便呀O(∩_∩)O~

这段代码值取得一个 DOM 元素,只添加了一个事件处理程序。所以这种技术占用的内存更少。所有用到按钮的事件都适合采用事件委托技术。

也可以为 document 对象添加一个事件处理程序,用来处理页面上发生的某种特定类型的事件。这种方式有如下优点:

  1. document 对象很快就能访问,而且可以在生命周期的任何时点为它添加事件处理程序。即只要可单击的元素出现在页面上,就立即具备了为它添加的事件处理程序的相应功能。
  2. 设置事件处理程序所需时间更少,因为只添加了一个事件处理程序嘛O(∩_∩)O~
  3. 整个页面占用的内存更少,提升了整体性能。

这些事件最适合采用事件委托技术:click、mousedown、mouseup、keydown、keyup 和 keypress。

2 移除事件处理程序

每当事件处理程序绑定元素时,运行中的浏览器代码与支持页面交互的 JavaScript 就会建立一个连接。这种连接越多,页面执行就越慢。所以,上一节介绍的事件委托技术,可以限制建立连接的数量。除此之外,还可以在不需要的时候移除事件处理程序。

有两种情况会导致内存中留有一些过时不用的“空事件处理程序”!

2.1 从文档中移除带有事件处理程序的元素

可能使用 DOM 操作(removeChild() 和 replaceChild() )或者使用 innerHTML 替换页面中的某一部分。如果带有事件处理程序的元素被 innerHTML 删除了,那么原来添加到元素中的事件处理程序可能无法被垃圾回收:

<div id="myDiv">    <input type="button" value="Click Me" id="myBtn"></div><script type="text/javascript">    var btn = document.getElementById("myBtn");    btn.onclick = function () {        document.getElementById("myDiv").innerHTML = "Processing...";    };</script>

这里的代码在单击按钮时,将按钮移除并替换成一个消息。有的浏览器(IE)会将对元素和对事件处理程序的引用都保存在内存中,所以最好手工移除事件处理程序:

<div id="myDiv">    <input type="button" value="Click Me" id="myBtn"></div><script type="text/javascript">    var btn = document.getElementById("myBtn");    btn.onclick = function () {        btn.onclick = null;//移除事件处理程序        document.getElementById("myDiv").innerHTML = "Processing...";    };</script>

注意,在事件处理程序中删除按钮会阻止事件冒泡。还有一点,目标元素在文档中是事件冒泡的前提。

2.2 卸载页面

IE8 及更早版本的浏览器,会在页面卸载之前没有清理干净事件处理程序,这样它们就会滞留在内存中。每次加载页面后在卸载(比如刷新操作),内存中滞留的对象数目就会增加,因为事件处理程序占用的内存没有被释放。

最好在页面卸载之前,通过 onunload 事件处理程序移除所有的事件处理程序。所以我们所说到的事件委托技术就可以很容易做到,因为需要跟踪的事件处理程序越少,移除它们就越容易。

原创粉丝点击