防抖-在事件触发后n秒后执行回调函数,如果n秒内再次触发,则重新计算时间。
使用
鼠标事件:click、mousemove、mouseover
键盘事件:keydown、keyup
window事件:resize,scroll
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
<title>debounce</title>
<style>
#container{
width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="debounce.js"></script>
</body>
</html>
var count = 1;
var container = document.getElementById('container');
function getUserAction() {
container.innerHTML = count++;
};
container.onmousemove = getUserAction;
代码
第一版:限定时间内不可重复触发
function debounce(fn,wait){
var timeout;
return function(){
clearTimeout(timeout)
timeout=setTimeout(fn,wait)
}
}
container.onmousemove = debounce(getUserAction, 1000);1s内不触发
this
不使用debounce函数,getUserAction的this指的是div #container,但是debounce的this指向的是window对象,使用apply处理this的指向。
function debounce(fn,wait){
var timeout;
return function(){
var context=this;
clearTimeout(timeout)
timeout=setTimeout(fn.apply(context),wait)
}
}
argument
不使用debounce函数,getUserAction传入e,会打印MouseEvent对象。但是使用debounce,getUserAction的e将打印为undefined。
function debounce(fn,wait){
var timeout;
return function(){
var context=this;
var args=argument;
clearTimeout(timeout)
timeout=setTimeout(fn.apply(context,args),wait)
}
}
返回值
如果getUserAction返回值,所以debounce需要返回值。
function debounce(fn,wait){
var timeout;
var result;
return function(){
var context=this;
var args=argument;
clearTimeout(timeout)
timeout=setTimeout(function(){
result=fn.apply(context,args)
},wait)
return result
}
}
立即执行
希望立即执行,在过n秒停止触发触发后再执行。而不是要等待n秒后,才能执行。
function debounce(fn,wait,immediate){
var timeout;
var result;
return function(){
var context=this;
var args=argument;
if(timeout)clearTimeout(timeout)
if(immediate){
val callNow=!timeout //表示已经执行
timeout=setTimeout(function(){
result=null
},wait)
if(callNow){
result=fn.apply(context,args)
}
}else{
timeout=setTimeout(function(){
result=fn.apply(context,args)
},wait)
}
return result
}
}
取消
希望有一个取消按钮,点击取消后,停止等待,可以理解触发。
function debounce(fn,wait,immediate){
var timeout;
var result;
var debounced=function(){
var context=this;
var args=argument;
if(timeout)clearTimeout(timeout)
if(immediate){
val callNow=!timeout //表示已经执行
timeout=setTimeout(function(){
timeout=null
},wait)
if(callNow){
result=fn.apply(context,args)
}
}else{
timeout=setTimeout(function(){
result=fn.apply(context,args)
},wait)
}
return result
}
debounced.cancel={
clearTimeout(timeout)
timeout=null
}
return debounced
}