首页 > 专栏 > 前端 > 文章详情
JavaScript事件中关于性能和内存问题,长期更新 发布于:2021-02-25 16:12:24   原创发表   查看:9  讨论:0
导致性能降低或内存泄漏的原因是多方面的:N2z易塔云建站-模板下载,web开发资源,技术博客
    □:每个函数都是对象。都会占用内存。N2z易塔云建站-模板下载,web开发资源,技术博客
    □:内存中的对象越多,性能就越差。N2z易塔云建站-模板下载,web开发资源,技术博客
目前了解的提升性能的方法有:N2z易塔云建站-模板下载,web开发资源,技术博客
N2z易塔云建站-模板下载,web开发资源,技术博客
一、事件委托。N2z易塔云建站-模板下载,web开发资源,技术博客
N2z易塔云建站-模板下载,web开发资源,技术博客
对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个时间处理程序,就可以管理某一类型的所有事件。N2z易塔云建站-模板下载,web开发资源,技术博客
例如:click事件会一直冒泡到document层,也就是说,我们可以为这个页面指定一个onclick事件处理程序,而不必给每个单击的元素分别添加事件处理程序。以下为例:
<ul id="myLinks">N2z易塔云建站-模板下载,web开发资源,技术博客
    <li id="to">三</li>N2z易塔云建站-模板下载,web开发资源,技术博客
    <li id="do">个</li>N2z易塔云建站-模板下载,web开发资源,技术博客
    <li id="click">li</li>N2z易塔云建站-模板下载,web开发资源,技术博客
</ul>
其中包含3个被单击后会执行操作的列表项。传统做法是:
var item1 = document.getElementById("to");N2z易塔云建站-模板下载,web开发资源,技术博客
var item2 = document.getElementById("do");N2z易塔云建站-模板下载,web开发资源,技术博客
var item3 = document.getElementById("this");N2z易塔云建站-模板下载,web开发资源,技术博客
EventUtil.addHandler(item1,"click",function(event){N2z易塔云建站-模板下载,web开发资源,技术博客
    location.href = "http://www.abc.com";N2z易塔云建站-模板下载,web开发资源,技术博客
});N2z易塔云建站-模板下载,web开发资源,技术博客
EventUtil.addHandler(item2,"click",function(event){N2z易塔云建站-模板下载,web开发资源,技术博客
    location.title = "change了一个title";N2z易塔云建站-模板下载,web开发资源,技术博客
});N2z易塔云建站-模板下载,web开发资源,技术博客
EventUtil.addHandler(item3,"click",function(event){N2z易塔云建站-模板下载,web开发资源,技术博客
    alert("你好")N2z易塔云建站-模板下载,web开发资源,技术博客
});
如果在一个复杂Web应用中,对所有可单击的元素都采用这种方式,那么结果就会有数不清的代码用于添加事件处理程序。N2z易塔云建站-模板下载,web开发资源,技术博客
此时,使用“事件委托”可以解决这个问题。N2z易塔云建站-模板下载,web开发资源,技术博客
事件委托,只需要在DOM树种尽量最高的层次上添加一个事件处理程序,如下:
// 事件委托N2z易塔云建站-模板下载,web开发资源,技术博客
var list = document.getElementById("myLinks");N2z易塔云建站-模板下载,web开发资源,技术博客
EventUtil.addHandler(list,"click",function(event){N2z易塔云建站-模板下载,web开发资源,技术博客
    event = EventUtil.getEvent(event);N2z易塔云建站-模板下载,web开发资源,技术博客
    var target = EventUtil.getTarget(event);//取得事件的目标哦N2z易塔云建站-模板下载,web开发资源,技术博客
    switch(target.id){N2z易塔云建站-模板下载,web开发资源,技术博客
        case "to" :N2z易塔云建站-模板下载,web开发资源,技术博客
            document.title = "change了一个title";N2z易塔云建站-模板下载,web开发资源,技术博客
            break;N2z易塔云建站-模板下载,web开发资源,技术博客
        case "do" :N2z易塔云建站-模板下载,web开发资源,技术博客
            location.href = "http://www.abc.com";N2z易塔云建站-模板下载,web开发资源,技术博客
            break;N2z易塔云建站-模板下载,web开发资源,技术博客
        case "this" :N2z易塔云建站-模板下载,web开发资源,技术博客
            alert("你好");N2z易塔云建站-模板下载,web开发资源,技术博客
            break;N2z易塔云建站-模板下载,web开发资源,技术博客
    };N2z易塔云建站-模板下载,web开发资源,技术博客
})
我们使用事件委托只给ul添加了一个onclick事件处理程序。由于所有的列表子元素,它们的事件会冒泡不是吗N2z易塔云建站-模板下载,web开发资源,技术博客
所以单击列表项的事件最终都会被这个函数处理。事件目标是被单击的列表项,所以通过检测id属性来决定是否采取适当的操作。注意:N2z易塔云建站-模板下载,web开发资源,技术博客
    □:与前面代码相比,这段代码的消耗更低,因为只取得了一个DOM,只添加了一个事件程序;N2z易塔云建站-模板下载,web开发资源,技术博客
    □:这种技术占用的内存更少。N2z易塔云建站-模板下载,web开发资源,技术博客
    □:如果可行的话,为document对象添加一个事件处理程序,用以处理页面上发生的各种特定类型的事件。优点:N2z易塔云建站-模板下载,web开发资源,技术博客
        △:document对象很快就可以访问,而且可以在页面生命周期的任何时点上为它添加事件处理程序(无需等待DOMContentLoaded或load事件)。只要可单击的元素呈现在页面上,就可以立即具备适当的功能;N2z易塔云建站-模板下载,web开发资源,技术博客
        △:在页面中设置时间处理程序所需的事件更少。只添加一个事件处理程序所需的DOM引用更少,说花的时间也更少;N2z易塔云建站-模板下载,web开发资源,技术博客
        △:整个页面占用的内存空间更少,能整体提升性能。N2z易塔云建站-模板下载,web开发资源,技术博客
最合适采用事件委托技术的事件:click、mousedown、mouseup、keydown、keyup、keypress。N2z易塔云建站-模板下载,web开发资源,技术博客
N2z易塔云建站-模板下载,web开发资源,技术博客
二、移除事件处理程序。N2z易塔云建站-模板下载,web开发资源,技术博客
N2z易塔云建站-模板下载,web开发资源,技术博客
每当将事件处理程序指定给元素时,浏览器与JavaScript代码之间就会建立一个链接。N2z易塔云建站-模板下载,web开发资源,技术博客
链接越多,页面执行起来就越慢。所以,在不需要的时候移除事件处理程序,也能解决一部分性能问题。N2z易塔云建站-模板下载,web开发资源,技术博客
内存中留的那些过时的“空事件处理程序(dangling event handler)”,也是造成Web程序内存性能问题的主因。N2z易塔云建站-模板下载,web开发资源,技术博客
如果某个元素(带有事件处理程序)被innerHTML删除,那么已经添加到元素中的事件就无法被当做垃圾回收。下面:
<div id="myDiv">N2z易塔云建站-模板下载,web开发资源,技术博客
    <input type="button" value="点击我吧" id="myBtn">N2z易塔云建站-模板下载,web开发资源,技术博客
</div>N2z易塔云建站-模板下载,web开发资源,技术博客
<script>N2z易塔云建站-模板下载,web开发资源,技术博客
    var btn = document.getElementById("myBtn");N2z易塔云建站-模板下载,web开发资源,技术博客
    btn.onclick = function(){N2z易塔云建站-模板下载,web开发资源,技术博客
        //somethingN2z易塔云建站-模板下载,web开发资源,技术博客
        document.getElementById("myDiv").innerHTML = "修改中。。。";N2z易塔云建站-模板下载,web开发资源,技术博客
    }N2z易塔云建站-模板下载,web开发资源,技术博客
</script>
一个按钮,被包裹在div中,单击此按钮就讲按钮移除并替换成一条消息。N2z易塔云建站-模板下载,web开发资源,技术博客
但是问题是:即使按钮移除了,它本身还带着一个事件处理程序。N2z易塔云建站-模板下载,web开发资源,技术博客
所以那么最好的方式是手工断开引用:
var btn = document.getElementById("myBtn");N2z易塔云建站-模板下载,web开发资源,技术博客
btn.onclick = function(){N2z易塔云建站-模板下载,web开发资源,技术博客
    //somethingN2z易塔云建站-模板下载,web开发资源,技术博客
    btn.onclick = null;//表达了断开N2z易塔云建站-模板下载,web开发资源,技术博客
    document.getElementById("myDiv").innerHTML = "修改中。。。";N2z易塔云建站-模板下载,web开发资源,技术博客
}
此时,我们先移除了按钮的事件处理程序。这样确保内存可以被再次利用,而从DOM中移除按钮也做到了干净利索。N2z易塔云建站-模板下载,web开发资源,技术博客
导致“空事件处理程序”的另一种情况,就是卸载页面的时候。N2z易塔云建站-模板下载,web开发资源,技术博客
IE8及早版本问题肯定是最多,但其他浏览器问题也不少。如果在页面被卸载前没有清理干净事件处理程序,那它们就会滞留在内存中。N2z易塔云建站-模板下载,web开发资源,技术博客
每次加载完页面再卸载页面时(可能是两个页面来回切换,也可能是点击了刷新按钮),内存中滞留的对象数目就会增加,因为事件处理程序占用的内存并没有被释放。N2z易塔云建站-模板下载,web开发资源,技术博客
一般来说,最好的方法就是在页面卸载之前,先通过onunload事件处理程序移除所有事件处理程序。N2z易塔云建站-模板下载,web开发资源,技术博客
只要是通过onload事件处理程序添加的东西,最后都要通过onunload事件处理程序将它们移除。

评论

  • 匿名