JS的防抖和节流
demo
by Mike Lin
HTML
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
<button class="throttle">
throttle
</button>
<button class="debounce">
debounce
</button>
JavaScript
const _now = Date.now || function () {
return new Date().getTime();
}
const throttle = function (func, wait, options = {}) {
let context, args, result;
let timeout = null;
let previous = 0;
const later = function () {
previous = options.leading === false ? 0 : _now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function () {
// 记录当前时间戳
const now = _now();
if (!previous && options.leading === false) previous = now;
const remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
// 解除引用,防止内存泄露
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) { // 最后一次需要触发的情况
timeout = setTimeout(later, remaining);
}
// 回调返回值
return result;
};
}
// 函数去抖(连续事件触发结束后只触发一次)
// sample 1: debounce(function(){}, 1000)
// 连续事件结束后的 1000ms 后触发
// sample 1: debounce(function(){}, 1000, true)
// 连续事件触发后立即触发(此时会忽略第二个参数)
/* eslint-disable */
const debounce = function (func, wait, immediate) {
let timeout, args, context, timestamp, result;
const later = function () {
const last = _now() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};
return function () {
context = this;
args = arguments;
timestamp = _now();
const callNow = immediate && !timeout;
if (!timeout) {
timeout = setTimeout(later, wait);
}
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
...