Open cobish opened 8 years ago
我们在开发中都会遇到这样一种情况:先给 Window 绑定一个 scroll 事件,然后打印日志,代码如下。打开浏览器,滚动一下鼠标,便会发现日志被频繁地打印出来。类似这样的事件还是 Window 的 resize 事件、输入框的 keyup 事件、拖拽时的 mousemove 事件等等。
scroll
resize
keyup
mousemove
$(window).on('scroll', function() { console.log(111); });
它们都有以下两个特点:
既然无法对这些事件进行改动,那么我们只能在被调用的函数中想办法优化了。因为使用场景的不同,所以有 函数防抖 和 函数节流 这两种优化方案,下面将逐一进行介绍。
函数防抖
函数节流
如果用手指一直按住一个弹簧,它将不会弹起直到你松手。函数防抖 debounce 就是给函数设置一个定时器,n 秒之后才调用函数,n 秒内如果再次设置定时器的话,则会重新定时 n 秒后执行函数。
debounce
函数防抖的简单实现:
/** * 函数防抖 * @param {Function} 调用的函数 * @param {Int} 时间 * @return {Function} 返回客户调用函数 */ var debounce = function(action, time) { var timer = null; return function() { var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function() { action.apply(context, args); }, time); }; };
这时如果我们再结合 Window 的 scroll 事件,可以发现控制台里的打印明细打印少了很多,而且几乎是在停止 scroll 了之后才会去调用 doResize 函数(主要是因为设置的事件为 500 毫秒)。
doResize
function doResize() { console.log(arguments); } var action = debounce(doResize, 500); $(window).on('resize', action);
如果将水龙头拧紧直到水是以水滴的形式流出,那你会发现每隔一段时间,就会有一滴水流出。函数节流 throttle 顾名思义就是节约使用函数次数的意思。
throttle
有一种场景,一个输入框在 keyup 之后需获取到输入的值去 ajax 请求,如果是正常实现的话,那 ajax 请求的数量则太大了。如果是使用 debounce 的话,则会在用户输入完毕后的 n 秒后才会去 ajax 请求。我们需要的只是减少 keyup 事件的触发,而不是完全禁止它等到最后一个 keyup 才触发。这时我们就可以使用函数节流throttle。
函数节流的简单实现:
/** * 函数节流 * @param {Function} 调用的函数 * @param {Int} 时间,单位毫秒 * @return {Function} 返回客户调用函数 */ var throttle = function(action, delay) { var last = 0; return function() { var curr = +new Date(); if (curr - last > delay) { action.apply(this, arguments); last = curr; } }; }
再结合输入框的 keyup 事件,就可以看出 keyup 调用的频率明显减少了。
function doInput() { console.log($(this).val()); } var action = throttle(doInput, 1000); $('#txt').on('keyup', action);
underscore.js 有对 debounce 和 throttle 的分别实现。将上面的代码修改如下:
underscore.js
// debounce var resizeAction = _.debounce(doResize, 500); $(window).on('resize', resizeAction); // throttle var keyupAction = _.throttle(doInput, 1000); $('#txt').on('keyup', keyupAction);
很棒
我们在开发中都会遇到这样一种情况:先给 Window 绑定一个
scroll
事件,然后打印日志,代码如下。打开浏览器,滚动一下鼠标,便会发现日志被频繁地打印出来。类似这样的事件还是 Window 的resize
事件、输入框的keyup
事件、拖拽时的mousemove
事件等等。它们都有以下两个特点:
既然无法对这些事件进行改动,那么我们只能在被调用的函数中想办法优化了。因为使用场景的不同,所以有
函数防抖
和函数节流
这两种优化方案,下面将逐一进行介绍。函数防抖
如果用手指一直按住一个弹簧,它将不会弹起直到你松手。函数防抖
debounce
就是给函数设置一个定时器,n 秒之后才调用函数,n 秒内如果再次设置定时器的话,则会重新定时 n 秒后执行函数。函数防抖的简单实现:
这时如果我们再结合 Window 的 scroll 事件,可以发现控制台里的打印明细打印少了很多,而且几乎是在停止 scroll 了之后才会去调用
doResize
函数(主要是因为设置的事件为 500 毫秒)。函数节流
如果将水龙头拧紧直到水是以水滴的形式流出,那你会发现每隔一段时间,就会有一滴水流出。函数节流
throttle
顾名思义就是节约使用函数次数的意思。有一种场景,一个输入框在 keyup 之后需获取到输入的值去 ajax 请求,如果是正常实现的话,那 ajax 请求的数量则太大了。如果是使用
debounce
的话,则会在用户输入完毕后的 n 秒后才会去 ajax 请求。我们需要的只是减少 keyup 事件的触发,而不是完全禁止它等到最后一个 keyup 才触发。这时我们就可以使用函数节流throttle
。函数节流的简单实现:
再结合输入框的 keyup 事件,就可以看出 keyup 调用的频率明显减少了。
使用 underscore.js
underscore.js
有对debounce
和throttle
的分别实现。将上面的代码修改如下:参考