JS–防抖函数、节流函数

JS–防抖函数、节流函数

防抖函数和节流函数,两者是极其相近的。

首先,根本目的都是为了限制函数触发的频率,提高用户体验;其次,两者的实现原理也是相近的,都可以使用setTimeout、时间戳等方式来实现。

适用的业务场景

防抖函数:

​ 监听浏览器窗口的resize事件;

​ 表单多次重复提交;

​ 输入框实时搜索事件;

​ 点拖拽事件;

​ 监听浏览器滚动事件等等

节流函数:

​ 手机端的下拉加载\上拉刷新更多操作;

​ 表单实时验证;页面数据实时保存等等

实现原理+代码

防抖函数:

​ 当连续触发事件时,在设定的时间内没有再次触发事件,函数A(你希望执行的业务函数)才会被执行一次.如果在设定时间内触发了事件,就重新开始计时.在实现逻辑上,其实就是在两个触发请求的时间间隔大于设定的时间时,总是取前一个触发请求调用函数A 。“活到最后的人才是赢家”。

节流函数:

​ 当连续触发事件时,保证在设定的时间内只调用一次函数A(你希望执行的业务函数)。“先到先得”,即在你设定的时间内,只会执行第一个触发的函数A,如果你在设定的时间内持续触发事件,那么那些事件会被忽略,直到超过设定的时间才会再次执行函数A

防抖函数:

/*个人理解,防抖函数就是网游里角色释放技能时需要进行蓄力/读条,没有蓄力/读条结束就重新按技能,角色会重新蓄力/读条,技能并没有释放出来。*/
// 延时函数版本
function (func, wait) {
	let timeout = null
	return function() {
		const that = this
		const args = arguments
		if(timeout) {clearTimeout(timeout)}
		timeout = setTimeout(function(){
			func.apply(that, args)
		},wait)
	}
}
// 时间戳版本
// 不太建议使用,代码有些冗余
function (func, wait) {
	let timeout = null
	let oldtime = 0
	return function() {
		const that = this
		const args = arguments
		const now = Date.now()
		if(now - oldtime < wait) {
			clearTimeout(timeout)
		}
        oldtime = now
		timeout = setTimeout(function(){
			func.apply(that, args)
		},wait)
	}
}

节流函数

/*个人理解,节流函数就是网游里角色释放技能后,需要等待技能冷却时间结束才能再次释放技能,期间无论怎么按技能键都无法释放出技能*/
// 时间戳版本
function (func, wait){
     let timeout = 0
     return function() {
        const that = this
        const args = arguments
        const now = Date.now()
        if(now - timeout > wait) {
            setTimeout(function() {
            	func.apply(that, args)
            }, wait)
            timeout = now
        }
     }
}
// 延时函数版本
function (func, wait){
     let timeout = 0
     return function() {
        const that = this
        const args = arguments
        if(!timeout) {
            timeout = setTimeout(function() {
                func.apply(that, args)
                timeout = null
            }, wait)
        }
     }
}

防抖、节流函数的立即执行和非立即执行

防抖函数

立即执行:即多次触发事件,第一次会马上执行函数,之后触发的事件在wait(设置的等待时间)内不会执行函数。相当于法师在读条放火球时,你再按火球技能没有任何效果。

非立即执行:即多次触发事件,只有前一个触发的事件A与后一个触发的事件B之间的时间间隔大于wait(设置的等待时间),前一个触发的事件才会执行一次函数。相当于法师在读条放火球时,你再按火球技能会重置读条。

function debounce(func, wait, immediate) {
	let timeout = null
	return function() {
	// 合并版本
      const that = this
      const args = arguments
      timeout ? clearTimeout(timeout) : immediate && func.apply(that, args)
      timeout = setTimeout(function () {
        !immediate && func.apply(that, args)
        timeout = null
      }, wait)
	}
}
function debounce(func, wait, immediate) {
	let timeout = null
	return function() {
	    const that = this
      	const args = arguments
		if(timeout) {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)
		}
	}
}

节流函数

立即执行:这一部分和防抖函数没有区别。

非立即执行:即多次触发事件,在wait(设置的等待时间)的时间范围内触发的第一个事件才会执行一次函数,其它的会被忽略,直到超出wait(设置的等待时间)。相当于法师释放了一个延时技能(延时3s),技能处于冷却中(冷却3s),在冷却时间内,无法重新释放该技能。

function throttle(func, wait, immediate){
     let timeout = null
     return function() {
     const that = this
     const args = arguments
     // 合并版本
     if(!timeout) {
         immediate && func.apply(that, args)
         timeout = setTimeout(function() {
         	!immediate && func.apply(that, args)
         	timeout = null
         }, wait)
     }
   }
}
function throttle(func, wait, immediate){
     let timeout = null
     return function() {
     const that = this
     const args = arguments
     if(immediate) {
     // 立即执行版本
     	if(!timeout) {
        	timeout = setTimeout(function() {
            	timeout = null
             }, wait)
             func.apply(that, args)
          }
       } else {
       // 不立即执行版本
       	if(!timeout) {
        	timeout = setTimeout(function() {
            	func.apply(that, args)
                timeout = null
            }, wait)
         }
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值