节流防抖与闭包

    今天项目上遇到了使用防抖函数的需求,所以查询了一下,在这里统一将节流函数与防抖函数做一下整理,并顺便说下闭包在这的用途。
首先说一下他们各自的作用:
1、防抖函数
使用场景:多次触发,只执行最后一次
2、节流函数
使用场景:多次触发,隔一段时间触发一次

在使用方式上,防抖函数与节流函数非常的相似,我们先来看下我最开始想到的简易版防抖

// 定义一个全局变量,用来判断函数是否已经执行
var timer;
function debounce(fn) {
	// 如果timer不为空,说明还没有执行函数,那就清理了上次触发,准备执行下次
	if (timer) {
		clearTimeout(timer)
	}
	timer = setTimeout(function() {
		fn()
	},200)
}

节流与防抖是很像的,只是清理未执行函数的时机不同,我们可以看到,防抖函数是在每次触发时都查看下是否有未执行的方法,如果有,直接不执行了,准备下一次;节流函数同样是在每次触发时都检测是否有未执行完成的,只是如果检测到有未执行完的函数,他会等函数执行完才可以被下一次触发,如下:

var timer;
function throttle(fn) {
	// 如果timer不为空,说明还没有执行函数,那就拒绝触发,等待函数执行完成
	if (timer) {
		return
	}
	timer = setTimeout(function() {
		fn()
		clearTimeout(timer)
	},200)
}

他们的区别应该是比较明显了。
    不过这种实现方式是有点问题的,他定义了一个全局的变量,那如果全局的需要使用节流防抖的函数都去调用他的话,timer的使用将会十分混乱,造成无法预知的问题。这个时候,闭包的好处就体现出来了,他可以为每个防抖函数划分一块区域,就不会造成混乱,看下他的代码:


function registDebounce(fn,delay) {
	var timer;
	var _that = this;
	return function ()  {
		var args = arguments; // 接收参数
		// 如果timer不为空,说明还没有执行函数,那就清理了上次触发,准备执行下次
		if (timer) {
			clearTimeout(timer)
		}
		timer = setTimeout(function() {
			fn.apply(_that,args);
		},delay)
	}
}

他的使用方式也发生了改变,从方法名就能看出来,由原来的直接调用,变为了现在的需要先注册再使用。

function print(i) { console.log("print",i) }
let printDebounce = registDebounce(print,200); // 注册防抖
// 调用防抖函数
for(let j = 1; j< 10; j++) {
	printDebounce(j); 
}
// 只输出 print 9

这样编写的防抖函数,就可以作为一个工具方法提供给全局使用了,因为每次注册的时候,都会给这个方法分配一个单独的空间,timer也是各自空间中的变量,各个方法不会互相影响。

同样可以看下节流函数代码:

function registThrottle(fn,delay) {
	var timer;
	var _that = this;
	return function () {
		var args = arguments; // 接收参数
		// 如果timer不为空,说明还没有执行函数,那就直接拒绝,等待函数执行完成
		if (timer) {
			return
		}
		timer = setTimeout(function() {
			fn.apply(_that,args);
			clearTimeout(timer)
		},delay)
	}
}

以上,如果有什么错误,欢迎指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值