在前端开发的过程中,我们经常会遇到持续触发的事件,如resize、scroll、mousemove等等,但是我们并不想在执行的时候频繁的去触发相应事件,此时函数防抖与节流可以很好的解决。
所谓防抖,是指触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行时间。
函数防抖分为非立即执行版与立即执行版
非立即执行版:
function debounce (func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout (function () {
func.apply(context, args);
}, wait);
}
}
立即执行版:
function debounce (func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
var runNow = !timeout;
timeout = setTimeout(function () {
timeout = null;
}, wait);
if (runNow) func.apply(context, args);
}
}
综合版:
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce (func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var runNow = !timeout;
timeout = setTimeout(function () {
timeout = null;
}, wait);
if (runNow) func.apply(context, args);
} else {
timeout = setTimeout(function () {
func.apply(context, args);
}, wait);
}
}
}
所谓节流,就是指连续触发事件但是在n秒中只执行一次函数
函数节流分为时间戳版与定时器版。
时间戳版:
function throttle (func, wait) {
var previous = 0;
return function () {
var now = Date.now();
var context = this;
var args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
定时器版:
function throttle (func, wait) {
var timeout;
return function () {
var context = this;
var args= arguments;
if (!timeout) {
timeout = setTimeout (function () {
timeout = null;
func.apply(context, args);
}, wait);
}
}
}
上述两个版本的区别是时间戳版的函数执行是在时间段开始的时候,而定时器版的函数执行是咋时间段结束的时候。
综合版:
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
*/
function throttle (func, wait, type) {
if (type === 1) {
var previous = 0;
}else if (type === 2) {
var timeout;
}
return function () {
var rcontext = this;
var args = arguments;
if (type === 1) {
var now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(function () {
timeout = null;
func.apply(context, args);
}, wait);
}
}
}
}