函数防抖
 
 
原理
 
- 通过定时器,让事件在触发后,经过指定长度的时间才去执行回调函数
- 而在这个等待的时间内,如果再次触发了事件,则清理当前定时器,重开一个新的定时器
- 这样,永远只有最后一次触发的事件会执行回调函数
- 防抖的意义是防止多次无意义地执行回调函数(是否无意义,根据具体情况而定)
应用场景
 
- 手风琴展示项的切换
- 轮播图切换
- 搜索框输入时的备选菜单
- 鼠标移动、页面滚动等触发频繁的事件
实现代码
 
function debounce(delay, cb) {
   let timer
   
   
   return function () {
     clearTimeout(timer)
     
     window.event = arguments[0]
     
     
     
     timer = setTimeout(() => {
       cb.apply(this, arguments)
     }, delay)
   }
 }
document.getElementById('input').addEventListener(
   'keyup', debounce(300, function (e) {
     console.log(event, e, this)
   })
 )
 
函数节流
 
 
原理
 
定时器方式
 
- 设置一个标识
- 如果标识为true,执行事件回调,并将标识改为false
- 然后使用定时器,在指定时间后将标识改为true
- 这样在指定的时间之内,该回调函数只会触发一次
时间戳方式
 
- 第一次执行回调函数时,记录其时间戳
- 当再次执行时,先判断当前时间戳距离上次执行时的时间戳是否大于了规定时间
- 如果大于,才能再次执行回调函数
实现代码
 
function throttle(delay, cb){
   
   let flag = true
   return function (){
	  if(flag){
	     
	     cb.apply(this,arguments)
	     flag = false
	  }
	  
	  setTimeout(() => {
	     flag = true
	  }, delay)
   }
}
function throttle(delay, cb){
	
	const firstTime = Date.now()
	return function(){
		
		if(Date.now() - firstTime >= delay){
			cb.apply(this,arguments)
			
            firstTime = Date.now()
		}
	}
}
document.querySelector('.key').addEventListener(
  'keyup', throttle(500, function (e) {
    console.log(event, e, this.value)
  })
)
 
总结
 
- 防抖和节流,其实从本质上来讲,目的是一样的,都是减少回调函数的执行次数
- 只是实现方式和落脚点不同,一个是频繁触发只执行最后一次,一个是规定时间内只执行一次
- 所以如何选择,还是要看具体的业务场景 
  - 如果是一顿操作猛如虎,最后只要执行一次,那就用防抖,最典型的就是搜索框,一连串输入结束后,再发送Ajax请求去服务器查询相应的备选列表
- 如果是周期性的执行一次回调,那肯定选节流了