虽说事件处理程序可以为现代 Web 页面添加很强的交互能力,但是不分青红皂白就添加大量的事件处理程序绝对是一种愚蠢的行为。
我们来分析一下:事件处理程序本质上是一种函数,是一种对象,存放在内存中,设置大量的事件处理程序会使内存中的对象变多,Web 程序的性能会变得越来越差,用户体验很不好。
为了更好地利用好事件处理程序,便出现了事件委托,用来提升性能。
事件委托(event delegation):把若干个子节点上的相同事件的处理函数绑定到它的父节点上去,在父节点上统一处理从子节点冒泡上来的事件,这种技术就叫做事件委托。
补充一下:事件委托并不局限于父节点与子节点之间。也可以这样玩,比如页面文档中有好多个处在不同位置地 button,都是绑定 click 事件,使用事件委托,我们可以把这些个事件统一绑定到 body 元素,然后再进行处理(虽然一般很少这么用)。
下面举例子逐步说明事件委托的优势:
<ul id="parent-list">
<li id="list-1">List 1</li>
<li id="list-2">List 2</li>
<li id="list-3">List 3</li>
<li id="list-4">List 4</li>
<li id="list-5">List 5</li>
</ul>
假设有上面的代码,我们现在有一个需求:就是无论单击上面的列表(ul)的哪个子列表(li),都会弹出一个框,来显示我们点击了哪个子列表。
需求不难吧?有了需求,接下来是该写 js 代码了,现在有两种方法放在你眼前:1. 为每个 li 子元素绑定 click 事件,然后设置处理函数; 2. 利用事件委托,为 ul 父元素绑定 click 事件,然后设置处理函数
// 方法一
var list1 = document.getElementById("list-1");
list1.addEventListener("click",function(){
alert(this.firstChild.nodeValue);
},false);
var list2 = document.getElementById("list-2");
list2.addEventListener("click", function() {
alert(this.firstChild.nodeValue);
}, false);
var list3 = document.getElementById("list-3");
list3.addEventListener("click", function() {
alert(this.firstChild.nodeValue);
}, false);
var list4 = document.getElementById("list-4");
list4.addEventListener("click", function() {
alert(this.firstChild.nodeValue);
}, false);
var list5 = document.getElementById("list-5");
list5.addEventListener("click", function() {
alert(this.firstChild.nodeValue);
}, false);
// 方法二
var parentList = document.getElementById("parent-list");
parentList.addEventListener("click",function(){
var target = event.target;
if(target.nodeName.toLowerCase() === "li"){
alert(target.firstChild.nodeValue);
}
},false);
看着上面的代码,我这里写几点方法二的优点:1. 减少了访问 dom 的次数,提升了性能;2. 将子元素的事件处理程序统一绑定到其父元素,减少了对内存的占用;3. 可以更好地管理事件处理程序,比如移除对某个事件处理程序的引用
注意:如果对各个子元素的需求不一样,我们还可以这样来改写上面的方法二:
// 方法二
var parentList = document.getElementById("parent-list");
parentList.addEventListener("click",function(){
var target = event.target;
if(target.nodeName.toLowerCase() === "li"){
switch(target.id){
case "list-1":
alert("学的越多,越觉得自己无知!");
break;
case "list-2":
alert("爱是一种艺术!");
break;
case "list-3":
target.innerhtml = "呵呵,我改了啊!";
break;
case "list-4":
target.style.background = "#aaa";
break;
case "list-5":
target.style.color = "red";
target.style.fontSize = "2em";
break;
default:
break;
}
}
},false);
因为事件委托依赖事件冒泡机制,所以,并不是所有的事件都可以进行事件委托。
最适合采用事件委托的事件包括:click、mousedown、mouseup、keydown、keyup 和 keypress。
事件委托只是一种非常不错的事件绑定的思想,所以不应该拘泥于上面的例子,要活学活用! ^_^
我们前面说过,事件处理程序存在于内存中,每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的 JavaScript 代码之间就会建立一个连接。这种连接越多,页面执行就越慢。前面所说的事件委托就是用来限制建立的连接数量。
还有,就是内存中那些使用完后不再使用的事件处理程序,如果不释放掉,也会影响 Web 应用程序的内存和性能。
<button id="button">提交</button>
var button = document.getElementById("button");
button.onclick = function(){
// 提交某个表单的操作代码
button.onclick = null; // 移除事件处理程序
event.target.firstChild.nodeValue = "提交中。。。";
};
总的原则就是:移除掉那些过时不再使用的事件处理程序,释放内存!
JavaScript 的内存管理和垃圾回收,是个略生僻的话题,因为在JavaScript 中不显式执行内存操作,不过最好了解它如何工作。
js具有自动回收垃圾的机制,即执行环境会负责管理程序执行中使用的内存。在C和C++等其他语言中,开发者的需要手动跟踪管理内存的使用情况。在编写js代码时候,开发人员不用再关心内存使用的问题,所需内存的分配 以及无用的回收完全实现了自动管理。
javaScript内存空间并不是一个经常被提及的概念,想要对JS的理解更加深刻,就必须对内存空间有一个清晰的认:栈与堆、复杂数据类型与基本数据类型、引用数据类型与堆内存
实际上并不是新建一个和原对象(数组也是对象)完全一样的对象,而是把原对象的内存地址直接复制给了另一个对象,也就是说两个对象都是指向同一个内存地址,所以实际上它们就是同一个对象。
php垃圾回收机制,对于PHPer来说是一个不陌生但是又不是很熟悉的内容。那么php是怎么实现对不需要的内存进行回收的呢?首先还是需要了解下基础知识,便于垃圾回收原理内容的理解。
JavaScript变量可以用来保存两种类型的值:基本类性值和引用类性值。所有变量(包括基本类型和引用类型)都存在于一个执行环境(也称为作用域)当中,具有自动垃圾收集机制的编程语言,开发人员不必关心内存分配和回收问题
计算机的内存由操作系统进行管理,所以普通应用程序是无法直接对内存进行访问的。应用程序只能向操作系统申请内存,通常的应用也是这么做的,在需要的时候通过类似malloc之类的库函数 向操作系统申请内存。
当项目以tab页签方式打开多个iframe窗口时,关闭tab页签同时也需要关闭iframe并释放内存资源,主要是针对IE浏览器。
今天遇到一个很有争议的问题,在这里分享一下,我相信对于即将面试前端的小伙伴会有帮助的。主要内容是围绕下边的问题展开的,文章涉及到的其他方面的知识点不展开叙述。
随着 Web 应用复杂程度越来越高,以及 NodeJS 大规模投入生产环境,许多 Web 应用都会长时间运行, JavaScript 的内存管理显得更为重要。JavaScript 具备自动回收垃圾的机制
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!