JavaScript必知必会(四)

使用事件委托降低重复的事件绑定

举个例子,如果有一个ul元素,下面有1000个子元素li,每个子元素都需要绑定一个点击事件,应该如何降低重复的事件绑定成本?

使用事件委托的方式,将li元素的点击事件委托给ul元素。

var ul = document.getElementsByTagName('ul')[0];
if(ul.addEventListener) {
    ul.addEvenetListener('click', function(e) {
        if(e.target.nodeName.toLowerCase() == 'li') {
            console.log(e.target.innerText);
        }
    }, false) // 第三个参数为false表示在冒泡阶段触发,否则在捕获阶段触发
} else {
    // 兼容IE浏览器,需要注意attachEvent、onclick、srcElement
    ul.attachEvent('onclick', function(e) {
        e = window.event || e;
        var target = e.srcElement;
        if(target.nodeName.toLowerCase() == 'li') {
            console.log(target.innerText);
        }
    })
}

JavaScript内存泄漏

当应用程序不再需要占用内存的时候,由于某些原因,内存没有被回收。JS是一种垃圾回收语言,它会周期性地检查先前分配的你是否可达,帮助开发者管理内存。垃圾回收语言的内存泄漏主要原因是不需要的引用。

现代的垃圾回收器改良了算法,但是本质是相同的:可达内存被标记,其余的被当作垃圾回收。

四种常见的JavaScript内存泄漏:

意外的全局变量

意外创造全局变量却不回收会导致内存泄漏,与全局变量相关的增加内存消耗的一个主因是缓存。缓存是为了重用,缓存必须要有一个大小上限才有用。高内存消耗导致缓存突破上限,因为缓存内容无法回收。

被遗忘的计时器或回调函数

计时器回调函数需要计时器停止才会被没收。

事件绑定的回调函数,移除对象时,要移除绑定的事件。现在浏览器可以做到移除不可达对象。

脱离DON节点的引用

有时,保存DOM节点内部数据结构很有用。假如你想快速更新表格的几行内容,把每一行DOM存成字典(JSON键值对)或者数组很有意义。此时,同样的DOM元素存在两个引用:一个在DOM树中,另一个在字典中。将来你决定删除这些行时,需要把两个引用都清除。

闭包

闭包是JavaScript开发的一个关键方面:匿名函数可以访问父级作用域的变量。

自定义事件

实现发布-订阅者模式

测试如下:

使用apply实现bind方法

call(thisObj, [arg1, [arg2, [arg3...]]])

call 方法可将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象。第一个参数是替换的调用对象,后面的参数是调用函数的参数,以逗号分隔。返回的替换后的函数运行结果。

apply(thisObj, [, argArray])

用指定的thisObj对象替换函数的运行上下文。第一个参数同call一样,第二个参数argArray为一个传参数组。返回的是替换上下文后函数运行的结果。

bind(thisObj, [arg1, [arg2, [arg3...]])

用指定对象替换当前对象,应用某一对象的一个方法。 说明:bind的thisObj参数也和call方法一样,thisObj如果未传,那么 Global 对象被用作 thisObj。arg1 … argN可传可不传。如果不传,可以在调用的时候再传。如果传了,调用的时候则可以不传,调用的时候如果你还是传了,则不生效。返回的是替换上下文后的函数。

使用apply实现bind

参考资料

使用事件委托减低重复的事件绑定arrow-up-right

4类JavaScript内存泄漏及如何避免arrow-up-right

Last updated