- 页面优化:减少DOM操作,防止高频操作DOM造成页面挂掉
我们在平时开发的过程中,会有一些场景:如input框输入内容去调接口,以及onmousemove,resize,onscroll等,正常情况会频繁的去触发事件,造成不必要的性能消耗,为了避免这种情况就会通过函数防抖和函数节流来处理。
函数防抖
_.debounce(func, [wait=0], [immediate])
事件响应函数(func)在一段时间(wait)后才会执行,如果在这段时间内再次触发该函数,会重新计算执行时间;当预定的时间内没有再次调用该函数,则执行func。
应用场景
- scroll时间滚动触发
- 搜索框输入查询
- 表单验证
- 按钮提交
- 浏览器窗口缩放,resize事件 ```javascript // 防抖函数 function debounce(func, wait, immediate) { let timeout; let result;
let debounced = function() { // this指向 let context = this; // event let args = arguments;
clearTimeout(timeout);
if(immediate) {
let callNow = !timeout;
timeout = setTimeout(function() {
timeout = null;
}, wait);
// 立即执行
if(callNow) {
result = func.apply(context, args);
}
} else {
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
}
return result; }
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null; }
函数节流
_.throttle(func, [wait=0], [options])
如果持续触发事件,每隔一段时间,只执行一次
应用场景
- DOM元素的拖拽功能实现
- 射击游戏
- 计算鼠标的移动距离
- 监听scroll滚动事件 ```javascript // 节流函数 // 1、使用时间戳节流 // 第一次触发,最后一次不触发 function throttle(func, wait) { let context; let args;
// 上一次执行的时间戳 let old = 0; return function() { context = this; args = arguments;
// 获取当前时间戳
let now = Date.now();
if(now - old > wait) {
// 立即执行
func.apply(context, args);
// 时间戳改变
old = now;
} } }
// 2、使用定时器 // 第一次不触发,最后一次触发 function throttle(func, wait) { let timeout; let context; let args;
return function() { context = this; args = arguments;
if(!timeout) {
timeout = setTimeout(function() {
timeout = null;
func.apply(context, args);
}, wait);
}
} }
// 3、时间戳和定时器结合 // 第一次触发,最后一次触发 function throttle(func, wait, options) { let timeout; let context; let args;
// 上一次执行的时间戳 let old = 0;
return function() { context = this; args = arguments; // 获取当前时间戳 let now = Date.now();
if(!options.leading && !old) {
old = now;
}
if(now - old > wait) {
// 第一次执行
if(timeout) {
clearTimeout(timeout);
timeout = null;
}
// 立即执行
func.apply(context, args);
// 时间戳改变
old = now;
} else if(!timeout && options.trailing) {
// 最后一次执行
timeout = setTimeout(function() {
old = Date.now();
timeout = null;
func.apply(context, args);
}, wait);
}
} } ```