<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>函数的防抖和节流</title> <!-- IMPORT CSS --> <link rel="stylesheet" href="css/reset.min.css"> <style> html, body { height: 500%; background: -webkit-linear-gradient(top left, lightblue, lightgreen, lightyellow, orange); } </style></head><body> <script src="node_modules/underscore/underscore.js"></script> <script> /* * https://underscorejs.org/ JS类库(提供很多项目中需要经常使用的方法) * * 函数的防抖(debounce):不是某个事件触发就去执行函数,而是在指定的时间间隔内,执行一次,减少函 数执行的次数 * * 函数的节流(throttle):为了缩减执行的频率,但不像防抖一样,一定时间内只能执行一次,而是一定时 间内能执行多次 */ /* * debounce:函数防抖 * @params * func:要执行的函数 * wait:间隔等待时间 * immediate:在开始边界还是结束边界触发执行(TRUE=>在开始边界) * @return * 可被调用的函数 */ function debounce(func, wait, immediate) { let result = null, timeout = null; return function (...args) { let context = this, now = immediate && !timeout; clearTimeout(timeout); // 重要:在设置新的定时器之前,我们要把之前设置的定时器都干掉,因为防抖的目的是等待时间内,只执行一次 timeout = setTimeout(() => { timeout = null; if (!immediate) result = func.call(context, ...args); }, wait); if (now) result = func.call(context, ...args); return result; } } /* * throttle:函数节流是为了缩减执行频率,当达到了一定的时间间隔就会执行一次 * @params * func:需要执行的函数 * wait:设置的间隔时间 * @return * 返回可被调用的函数 */ let throttle = function (func, wait) { let timeout = null, result = null, previous = 0; // 上次执行时间点 return function (...args) { let now = new Date, context = this; // remaining 小于等于0,表示上次执行至此所间隔时间已经超过一个时间间隔 let remaining = wait - (now - previous); if (remaining <= 0) { clearTimeout(timeout); previous = now; timeout = null; result = func.apply(context, args); } else if (!timeout) { timeout = setTimeout(() => { previous = new Date; timeout = null; result = func.apply(context, args); }, remaining); } return result; }; }; let count = 0; function fn() { console.log(++count); } let lazyFn = _.throttle(fn, 1000); window.onscroll = lazyFn; </script></body></html>