防抖和节流是前端性能优化中常常提及的点,上面来做个简略介绍和实现形式。
说一下防抖和节流函数的利用场景,并简略说下实现形式
防抖
- 防抖函数的利用场景:防抖是指,触发事件后在 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) );