// 防抖
function debounce(func,wait){
var timeout;
return function(){
var self = this;
var args = arguments;
if(timeout) clearTimeout(timeout);
timeout = setTimeout(()=>{
func.apply(self,args);
},wait)
}
}
// 节流
function throttle(func,wait){
var timeout;
return function(){
var self = this;
var args = arguments;
if(!timeout){
timeout = setTimeout(()=>{
timeout = null;
func.apply(self,args)
},wait)
}
}
}
https://www.cnblogs.com/momo798/p/9177767.html
var timer; // 维护同一个timer
function debounce(fn, delay) {
clearTimeout(timer);
timer = setTimeout(function(){
fn();
}, delay);
}
// test
function testDebounce() {
console.log('test');
}
document.onmousemove = () => {
debounce(testDebounce, 1000);
}
上面例子中的debounce就是防抖函数,在document中鼠标移动的时候,会在onmousemove最后触发的1s后执行回调函数testDebounce;如果我们一直在浏览器中移动鼠标(比如10s),会发现会在10 + 1s后才会执行testDebounce函数(因为clearTimeout(timer)),这个就是函数防抖。
在上面的代码中,会出现一个问题,var timer只能在setTimeout的父级作用域中,这样才是同一个timer,并且为了方便防抖函数的调用和回调函数fn的传参问题,我们应该用闭包来解决这些问题。
/**
* 防抖函数
* @param method 事件触发的操作
* @param delay 多少毫秒内连续触发事件,不会执行
* @returns {Function}
*/
function debounce(method,delay) {
let timer = null;
return function () {
let self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
method.apply(self,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
https://blog.csdn.net/a5161586/article/details/83149859
/**
*@param fn {function} 事件触发执行的函数
*@param wait {number} 固定时间(事件停止触发多久之后执行函数)
*/
debounce(fn,wait)
function debounce(fn,wait){
var timer;
return function(){
var args = Array.prototype.slice.apply(arguments);
if(timer){
clearTimeout(timer);
};
timer = setTimeout(function(){
fn.apply(this,args);
},wait);
}
}
<body>
<div id="app">111</div>
<h2></h2>
<script>
var app = document.getElementById('app')
var h2 = document.querySelector('h2')
var count = 0;
//频繁触发
/*app.onmousemove = function() {
h2.innerHTML = count
count++
}*/
//防抖函数
/*function debounce(func,wait){
var timeout;
return function(){
clearTimeout(timeout)
timeout=setTimeout(func, wait);
}
}
app.onmousemove = debounce(function(){
h2.innerHTML = count
count++
},1000)*/
/*在上面的代码中,会出现一个问题,var timer只能在setTimeout的父级作用域中,
这样才是同一个timer,并且为了方便防抖函数的调用和回调函数fn的传参问题,
我们应该用闭包来解决这些问题。*/
//改进后防抖函数
function debounce(func,wait){
var timeout;
return function(){
var context = this
var args = arguments
clearTimeout(timeout)
timeout=setTimeout(function(){
func.apply(context,args)
}, wait);
}
}
app.onmousemove = debounce(function(ev){
console.log(ev)
h2.innerHTML = count
count++
},1000)
</script>
</body>
定义:事件触发后执行函数执行期间内事件再次触发,执行函数将不会执行,等规定时间之后事件触发,执行函数方可再次执行。
原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时
防抖有一个问题,那就是如果事件一直在触发,那么执行函数永远都得不到执行。这种情况下,函数节流此时是较好的方法。
它与防抖最大的区别就是,无论事件触发多么频繁,都可以保证在规定时间内可以执行一次执行函数。
函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。如下图,持续触发scroll事件时,并不立即执行handle函数,每隔1000毫秒才会执行一次handle函数。
定时器实现节流函数:
function throttle(fn, delay) {
var timer;
return function () {
var _this = this;
var args = arguments;
if (timer) {
return;
}
timer = setTimeout(function () {
fn.apply(_this, args);
timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器
}, delay)
}
}
//测试用例:
function testThrottle(e, content) {
console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 1000); // 节流函数
document.onmousemove = function (e) {
testThrottleFn(e, 'throttle'); // 给节流函数传参
}
函数节流的目的,是为了限制函数一段时间内只能执行一次。因此,定时器实现节流函数通过使用定时任务,延时方法执行。在延时的时间内,方法若被触发,则直接退出方法。从而,实现函数一段时间内只执行一次。
根据函数节流的原理,我们也可以不依赖 setTimeout实现函数节流。
时间戳实现节流函数:
function throttle(fn, delay) {
var previous = 0;
// 使用闭包返回一个函数并且用到闭包函数外面的变量previous
return function() {
var _this = this;
var args = arguments;
var now = new Date();
if(now - previous > delay) {
fn.apply(_this, args);
previous = now;
}
}
}
// test
function testThrottle(e, content) {
console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 1000); // 节流函数
document.onmousemove = function (e) {
testThrottleFn(e, 'throttle'); // 给节流函数传参
}
其实现原理,通过比对上一次执行时间与本次执行时间的时间差与间隔时间的大小关系,来判断是否执行函数。若时间差大于间隔时间,则立刻执行一次函数。并更新上一次执行时间。