防抖和节流是前端性能优化中常常提及的点,上面来做个简略介绍和实现形式。
说一下防抖和节流函数的利用场景,并简略说下实现形式
防抖
- 防抖函数的利用场景:防抖是指,触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会从新计算函数执行工夫。常见场景有:键盘输入实时搜寻时 input 事件防抖,浏览器窗口扭转 resize 事件防抖等等。
- 实现形式:利用闭包和 setTimeout 来实现,创立一个 debounce 函数,定义一个 timer 变量用来保留定时器,返回一个函数,在函数内治理定时器和 fn 的执行机会。
// 防抖函数 -ES6 版本
function debounce (fn, time = 200) {
let timer = null;
return function (...args) {if (timer) clearTimeout(timer);
timer = setTimeout(() => {fn.apply(this, args);
}, time);
}
}
// 防抖函数 -ES5 版本
function debounceES5 (fn, time) {
time = time || 200;
var timer = null;
return function () {if (timer) clearTimeout(timer);
var that = this;
var args = arguments;
timer = setTimeout(function () {fn.apply(that, args);
}, time);
}
}
<div>
<span> 测试防抖 debounce</span>
<input type="text" id="input_1">
</div>
// 测试防抖
let input_1 = document.getElementById('input_1');
input_1.addEventListener('input', debounce(function (event) {console.log('event =', event); // InputEvent 事件对象
console.log('this =', this); // input_1 的 DOM 对象
}));
// 测试防抖传参
// input_1.addEventListener('input', debounce(function (a, b, event) {// console.log('a =', a); // 1
// console.log('b =', b); // 2
// console.log('event =', event); // InputEvent 事件对象
// console.log('this =', this); // input_1 的 DOM 对象
// }).bind(input_1, 1, 2) );
function handle (a) {console.log('handle');
console.log(a);
}
let debounceHandle = debounceES5(handle, 1000);
// 防抖函数参数
// let timer = setInterval(debounceHandle, 200);
let timer = setInterval(() => { debounceHandle(1) }, 200);
setTimeout(function() {clearInterval(timer);
}, 2000);
// 输入:2 秒后,打印出 handle 1
节流
- 节流函数的利用场景:节流是指,在间断的工夫内一直触发同个事件,会每隔 n 秒才执行一次这个事件。常见场景有:懒加载要监听计算滚动条的地位,用户点击提交按钮只容许肯定工夫内点击一次等等。
- 实现形式:利用闭包和 setTimeout 配合一个标识符来实现,创立一个 throttle 函数,定义一个 canRun 变量用来保留当次工作是否可执行,返回一个函数,在函数内治理 canRun 的值和 fn 的执行机会,当 canRun 为 false 时间接返回。
// 节流函数 -ES6 版本
function throttle (fn, time = 200) {
let canRun = true;
return function (...args) {if (!canRun) return;
canRun = false;
setTimeout(() => {fn.apply(this, args);
canRun = true;
}, time);
}
}
// 节流函数 -ES5 版本
function throttleES5 (fn, time) {
time = time || 200;
var canRun = true;
return function () {if (!canRun) return;
canRun = false;
var that = this;
var args = arguments;
setTimeout(function () {fn.apply(that, args);
canRun = true;
}, time);
}
}
<div>
<span> 测试节流 throttle</span>
<input type="text" id="input_2">
</div>
// 测试节流
let input_2 = document.getElementById('input_2');
input_2.addEventListener('input', throttle(function (event) {console.log('event =', event); // InputEvent 事件对象
console.log('this =', this); // input_2 的 DOM 对象
}));
// 测试节流传参
// input_2.addEventListener('input', throttle(function (a, b, event) {// console.log('a =', a); // 1
// console.log('b =', b); // 2
// console.log('event =', event); // InputEvent 事件对象
// console.log('this =', this); // input_2 的 DOM 对象
// }).bind(input_2, 1, 2) );