除夕好!望眉目有山河,清澈明朗。愿心中有丘壑,一往无前。
防抖
事件响应函数在一段时间后才执行,如果在这段时间内再次调用,则重新计算执行时间。当预定的时间内没有再次执行该函数,则执行doSomething。
应用场景
- scroll事件滚动触发
- 搜索框输入查询
- 表单验证
- 按钮提交事件
- 浏览器窗口播放,resize事件
function debounce(func, wait, immediate){
var timeout, result;
let decounced = function(){
// 改变内部this指向
let context = this;
// 获取event事件对象,取鼠标事件执行函数参数
let args = arguments;
// 每次触发事件执行函数的时候先清空定时器
clearTimeout(timeout);
if(immediate){
let callNow = !timeout; // callNow与定时器相关
// 延迟事件到了就把定时器清空以便可以重新执行func函数
timeout = setTimeout(() => {
timeout = null;
}, wait);
//表示立即执行
if(callNow) result = func.apply(context, args); //执行事件绑定真正执行函数的上下文和参数
}else {
//不会立即执行
timeout = setTimeout(function(){
result = func.apply(context, args);
}, wait);
}
// 真正执行函数的返回值
return result;
}
// 取消定时器中的事件
decounced.cancel = function(){
clearTimeout(timeout);
timeout = null; // 防止内存泄漏
}
return decounced;
}
// 要防抖的函数
function doSomeThing(e){
console.log(this) // 绑定事件的对象 btn
console.log(e) // event事件对象 点击事件对象
// 做某些事情...
return '想要的结果';
}
// 使用
let doSome = debounce(doSomeThing, 5000);
// 绑定点击事件,执行 取消定时器中事件 函数
btn.onclick = function(){
doSome.cancel();
}
节流
如果持续触发事件,每隔一段时间,只会执行一次事件。
应用场景
- DOM元素拖拽功能的实现
- 射击游戏
- 计算鼠标移动的距离
- 监听scroll滚动事件
function throttle(func, wait, options){
let context, args, timeout;
let old = 0;
if(!options) options = {};
return function(){
context = this;
args = arguments;
let later = function(){
old = new Date().valueOf();
timeout = null;
func.apply(context, args);
}
let now = new Date().valueOf();
if(options.leading === false && !old){
old = now;
}
if(now - old > wait){
// 第一次会直接执行
if(timeout){
clearTimeout(timeout);
timeout = null;
}
func.apply(context, args);
old = now;
}else if(!timeout && options.trailing !== false){
// 最后一次也会被执行
timeout = setTimeout(later, wait);
}
}
}
function doSomeThing(e){
console.log(this) // 绑定事件的对象 btn
console.log(e) // event事件对象 点击事件对象
container.innerHTML = count++;
return '想要的结果';
}
let doSome = throttle(doSomeThing, 1000, {
leading: true,
trailing: true
})
// 如果想禁用第一次首先执行的话,第三个参数传递, { leading: false },如果想禁用最后一次执行的话,第三个参数传递{ trailing: false }