浏览器中某些计算和处理要比其他的昂贵,例如在浏览器中操作DOM比非DOM交互需要更多的内存和CPU的事件,连续尝试进行过多的DOM相关操作可能UI导致浏览器挂起,有时甚至会崩溃。尤其在IE中使用onresize事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize事件处理程序内部如果尝试进行DOM操作,其高频率的更改可能会让浏览器崩溃。为了解决短时间内重复调用事件的这个问题,可以使用函数节流和抖动方法。
函数节流
函数节流背后的思想是指某些代码不可以在没有间断的情况下连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。实现函数的基本模式如下:
var processor = {
timer: null,
//实际进行的处理方法
handle:function(){
//实际执行的代码
},
//初始处理调用的方法
percess: function(){
//清除缓存好的timer,来阻止之前的调用被执行
clearTimeout(this.timer);
var that = this;
this.timer = setTimeout(function(){
that.handle();
},100)
}
};
//尝试开始执行
processor.process();
这个模式可以使用throttle()函数来简化,这个函数可以自动进行定时器的设置和清除,如下例:
function throttle(method,context){
clearTimeout(method.timer);
method.timer = setTimeout(function(){
method.call(context);
},100);
}
throttle()函数接受两个参数,执行的函数和作用域。
前面提到,节流在resize事件中最常用。如果你基于该事件来改变页面布局的话,最好控制处理事件的频率。假设有一个 <div>
元素需要保持它的高度始终等于宽度那么实现这一功能的函数如下:
function resizeDiv(){
var div = document.getElementById('myDiv');
div.style.height = div.offsetWidth + 'px';
}
考虑到节流的话就可以用到throttle()函数了,用例如下:
function resizeDiv(){
var div = document.getElementById('myDiv');
div.style.height = div.offsetWidth + 'px';
}
window.onresize = function(){
throttle(resizeDiv);
}
只要代码是周期性执行的,都应该使用节流。
函数防抖
防抖意思是防止抖动,事件连续触发,延迟一段时间再执行,如果在延迟的时间内继续触发,会重新计算时间。
function debounce(){
var timer;
return function(){
if(timer) clearTimeout(timer);
timer=setTimeout(function(){
//处理事件
}, 1000);
}
}
window.onscroll=debounce();