函数防抖
适用场景:
- 按钮提交:防止多次提交按钮,只执行最后提交的一次
- 搜索框联想:防止联想发送请求,只发送最后一次输入
简便方法
函数防抖的指导思想是:某些代码可以在没有间断的情况下重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔后执行代码。当第二次调用该函数的时候,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作没有意义。然而,如果前一个定时器尚未执行,其实就是替换为一个新的定时器,目的是只有在执行函数的请求停止了一段时间后才执行。
上代码:
function debounce(method,context){
clearTimeout(method.tId); //{1}
method.tId = setTimeout(function(){
method.call(context); //{2}
},100);
}
debounce方法接收两个参数:要执行的函数及在哪个作用域中执行。{1}首先清除之前设置的任何定时器,定时器ID是储存在函数的tId属性中的。定时器代码{2}使用call来确保方法在适当的环境中执行。如果没有给出第二个参数,那么就在全局作用域内执行该方法。
传入延时参数
关于防抖函数的写法,网上还看到另一种方法,可以传入延时时间作为参数,使用了闭包,但是大同小异。
原文在这里
function debounce(method,delay){
var timer=null;
return function(){
var context=this, args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}
立即执行
有时候希望函数能够立即执行,然后间隔n秒之后才能被再次触发,这种就很适合用在给按钮做幂等的场景。
function debounce(method, delay){
var timer=null
return function(){
var context=this, args=arguments, callNow = !timer;
clearTimeout(timer);
timer=setTimeout(function(){
timer = null;
},delay);
if(callNow) method.apply(context,args);
}
}
函数节流
适用场景:
- 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动
- 缩放场景:浏览器resize
浏览器的DOM操作比起非DOM交互需要更多的内存和cpu时间,连续过多的DOM操作可能会导致浏览器挂起甚至崩溃。比如使用onresize,onscroll这些可能会被连续触发的事件的时候,如果事件处理程序中进行了过多地DOM操作,可能就会使得浏览器崩溃。而为了绕开这个问题,可能就需要使用到函数节流。
比如:
function resizeDiv(){ //在窗口尺寸改变的时候,调整div的高度
var div = document.getElementById("myDiv");
console.log(div.offsetWidth);
div.style.height = div.offsetWidth + "px";
}
window.onresize = function(){
resizeDiv();
}
上面的代码在我简单的拉伸窗口的时候被连续执行了,如果是更复杂的DOM操作,很可能使得浏览器崩溃。其实我想要的只是在我改变完窗口大小后,再调整一次myDiv的高度。
使用时间差
在开始处多设置了一个开始时间,然后在每次调用的时候判断当前时间是否有超过预设的时间间隔,如果超过了,就立即执行一次事件处理函数,然后再将当前时就按记录下来,如此往复。
代码如下:
function throttle(method, duration){
var begin=new Date(); //{1}
return function(){
var context=this, args=arguments, current=new Date();
if(current-begin>=duration){ //{2}
method.apply(context, args);
begin=current;
}
}
}
使用定时器
还可以使用定时器来实现。
function throttle(method, duration) {
var timer;
return function () {
var context = this, args = arguments;
if (!timer) {
timer = setTimeout(function () {
method.apply(context, args);
timer = null;
}, duration)
}
}
}
以window.onresize为例,不直接执行事件处理函数了。
window.onresize = throttle(resizeDiv, 1000);
这样,多数情况下,用户察觉不到变化,但能够给浏览器节省很多计算。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。