函数节流和防抖在前端开发中应用广泛, 例如: 函数防抖可以用于对用户输入的自动补全操作, 函数节流可以用于对用户浏览行为的捕捉.
防抖
函数在事件触发 n 秒后才执行, 如果一个事件触发的 n 秒内又触发了这个事件, 那就以新的事件的触发时间为准
基本版
- function denounce(func, wait) {
- var timeout;
- return function (){
- clearTimeout(timeout);
- setTimeout(func, wait);
- }
- }
解决 setTimeout 执行过程中 this 指向问题
- function debounce (func, wait){
- var timeout
- return function (){
- var that = this
- clearTimeout(timeout)
- timeout = setTimeout(function(){
- func.apply(that)
- }, wait)
- }
- }
解决 event 参数传递
- function debounce (func, wait){
- var timeout
- return function (){
- var args = arguments
- var that = this
- clearTimeout(timeout)
- timeout = setTimeout(function(){
- func.apply(that, args)
- }, wait)
- }
- }
加上可立即执行判断
- function debounce (func, wait, immediate){
- var timeout
- return function (){
- var args = arguments
- var that = this
- clearTimeout(timeout)
- if (immediate){
- if (!timeout){
- func.apply(that, args)
- }
- timeout = setTimeout(function(){
- timeout = null
- }, wait)
- } else {
- timeout = setTimeout(function(){
- func.apply(that, args)
- }, wait)
- }
- }
- }
加上返回值
- function debounce (func, wait, immediate){
- var timeout, result
- return function (){
- var args = arguments
- var that = this
- clearTimeout(timeout)
- if (immediate){
- if (timeout){
- result = func.apply(that, args)
- }
- timeout = setTimeout(function(){
- timeout = null
- }, wait)
- } else {
- timeout = setTimeout(function(){
- func.apply(that, args)
- }, wait)
- }
- return result
- }
- }
增加取消上次防抖等待
- function debounce (func, wait, immediate){
- var timeout, result
- var debounced = function (){
- var args = arguments
- var that = this
- clearTimeout(timeout)
- if (immediate){
- if (!timeout){
- result = func.apply(that, args)
- }
- timeout = setTimeout(function(){
- timeout = null
- }, wait)
- } else {
- timeout = setTimeout(function(){
- func.apply(that, args)
- }, wait)
- }
- return result
- }
- debounced.cancel = function(){
- clearTimeout(timeout)
- timeout = null
- }
- return debounced
- }
节流
函数在每个规定时间间隔内只会被触发一次
两种基本方式
时间戳版 (效果: 第一次触发马上执行, 最后一次触发不会有效果)
- function throttle(func, wait) {
- var pre = 0
- return function(){
- var now = Date.now()
- var that = this
- var args = arguments
- if (now - pre> wait) {
- func.apply(that, args)
- pre = now
- }
- }
- }
定时器版 (效果: 第一次触发延迟执行, 最后一次触发有效果)
- function throttle(func, wait){
- var timeout
- return function(){
- var that = this
- var args = arguments
- if (!timeout) {
- timeout = setTimeout(function (){
- timeout = null;
- func.apply(that, args)
- }, wait)
- }
- }
- }
结合可配置版
- function throttle(func, wait, options) {
- var timeout, context, args, result;
- var previous = 0;
- if (!options) options = {};
- var later = function() {
- previous = options.leading === false ? 0 : new Date().getTime();
- timeout = null;
- func.apply(context, args);
- if (!timeout) context = args = null;
- };
- var throttled = function() {
- var now = new Date().getTime();
- if (!previous && options.leading === false) previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0 || remaining> wait) {
- if (timeout) {
- clearTimeout(timeout);
- timeout = null;
- }
- previous = now;
- func.apply(context, args);
- if (!timeout) context = args = null;
- } else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
- }
- };
- return throttled;
- }
来源: http://www.jianshu.com/p/12483364bd13