1、函数节流(throttle)
函数节流是指☞规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
函数节流常用场景:
- DOM 元素的拖拽功能实现(mousemove)
- 搜索联想(keyup)
- 计算鼠标移动的距离(mousemove)
- 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
- Canvas 模拟画板功能(mousemove)
function throttle1(fn, delay){
//记录上一次函数触发时间
var lastTime = 0;
return function(){
//记录当前函数触发的时间
var nowTime = Date.now();
if(nowTime-lastTime > delay){
//修正this的指向
fn.call(this);
lastTime = nowTime;
}
}
}
document.onscroll = throttle1(function(){console.log('scroll事件被触发了' + Date.now() + this)},300);
其原理是用时间戳来判断是否已到回调函数该执行时间,记录上一次执行的时间戳,然后每次触发scroll事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否达到规定时间段。如果是,则执行,并更新上一次执行时间戳,如此循环。
上例中用了闭包的特性,可使变量lastTime的值长期保存在内存中。
函数节流二
//声明一个变量当标记,记录回调函数是否在运行
var canRun = true;
document.getElementById("throttle").onscroll = function(){
if(!canRun){
// 如果在执行中,则直接return
return;
}
canRun = false;
setTimeout(function(){
console.log("函数节流");
canRun = true;
}, 300);
};
2、函数防抖(debounce)
函数防抖是指☞在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。也就是一定的时间内,只执行一次代码。
函数防抖常用场景:
- 每次 resize/scroll 触发统计事件
- 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)
<button id='btn'>Button</button>
<script>
function debounce(fn, delay){
//记录上一次的计时器
var timer = null;
return function(){
//清除上一次计时器
var that = this;
clearTimeout(timer);
timer = setTimeout(function(){
fn.apply(that);
debugger;
},delay)
}
}
document.getElementById('btn').onclick = debounce(function(){
console.log('触发点击事件' + Date.now() + this);
},500);
</script>