JS防抖与节流

CSDN话题挑战赛第2期
参赛话题:前端技术分享

说在前面

每年的下半年也是一个求职高峰期,JS中的防抖和节流是前端开发必备知识点,也是一种前端性能优化手段。在求职过程中,也会经常被面试官问到,所以防抖、节流对于前端开发来时,必须要掌握。

引言

弄懂这篇文章,你就能搞懂什么是防抖和节流,如何手写实现,以及防抖节流在项目中的应用场景。

什么是防抖和节流?

防抖与节流都是为了防止高频率触发某个动作,导致响应跟不上动作,造成页面卡顿,如:连续点击多次表单提交按钮造成多次重复提交处理、监听页面滚动处理、鼠标移动、窗口大小改变、输入框输入事件……
防抖和节流属于一种性能优化手段,可以通过控制函数执行时机来解决。
下面分别来介绍防抖和节流,以及手写实现。

防抖

将触发的多次事件合并成一个事件,只执行最后一次事件,具体实现:通过设置一个延迟执行时间,事件会在延迟时间后执行,延迟时间的期间内如果有事件触发,会重新计时。

function debounce ( fn , delay ) {
	let timer = null
	return function run ( ) {
		if ( timer ) {
			clearTimeout( timer )
		}
		timer = setTimeout( () => {
			fn()
		} , delay )
	}
}

防抖也可借用第三方 js 库实现,如 lodash.js 中的 _.debounce()

节流

控制频繁触发某个事件响应的频率,使高频触发变成每隔一段时间触发一次,这个时间之内触发的事件会被忽略,不去执行。具体实现:结合锁机制,控制当前执行只允许一个事件操作,操作完后才会解锁当前执行体,释放给其它事件。

function throttle ( fn , delay ) {
	let lock = false // 未上锁
	return function run ( ) {
		if ( !lock ) {
			// 未上锁可执行
			lock = true  // 进入执行时,对当前执行体上锁,禁止其它事件执行
			const timer = setTimeout( () => {
				fn()
				lock = false  // 当前触发事件执行完后,解锁释放执行体。
			} , delay)
		}
	}
}

节流也可借用第三方 js 库实现,如 lodash.js 中的 _.throttle()

案例

下面写了一个防抖和节流的应用场景,可以自行拷贝代码,打开页面查看效果。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <label>搜索框:</label><input id="name" type="search" oninput="search()">
    <button onclick="confirm()">提交</button>
    <script>
      /**
       * @function:防抖
       * @description:将高频率多次触发事件合并成一个事件
       * @param {Function} fn:事件触发要做的处理函数
       * @param {Object} delay:自定义延迟执行时间
       * @return {Function} run:事件触发要执行的回调函数
       * @author yehuixiang
       */
      function debounce(fn, delay) {
        let timer = null
        return function run() {
          timer && clearTimeout(timer)
          timer = setTimeout(() => {
            fn()
          }, delay)
        }
      }
      /**
       * @function:提交
       * @description:提交表单内容,传给后台
       * @return void
       * @author yehuixiang
       */
      function submit() {
        const input = document.querySelector('#name')
        console.log(input)
        alert(`已提交:${input.value}`)
      }
      var confirm = debounce(submit, 500)

      /**
       * @function:节流
       * @description:将高频率多次触发事件变成每隔一段时间执行一次,也就是有节制地触发
       * @param {Function} fn:事件触发要做的处理函数
       * @param {Object} delay:自定义执行间隔
       * @param {Number} oldTime:旧时间指针
       * @param {Number} nowTime:当前时间指针
       * @return {Function} run:事件触发要执行的回调函数
       * @author yehuixiang
       * @version 时间戳版本
       */
      function throttle(fn, delay) {
        let oldTime = 0
        return function run() {
          const nowTime = +new Date()
          if (nowTime - oldTime > delay) {
            oldTime = nowTime
            const timer = setTimeout(() => {
              fn()
              clearTimeout(timer)
            }, delay)
          }
        }
      }
      /**
       * @function:实时搜索
       * @description:将输入值传给接口实时查询当前搜索词相关内容
       * @return void
       * @author yehuixiang
       */
      function getKeys() {
        // 调取后台关键词搜索接口,获取搜索结果相关处理
        console.log('从后台实时获取相关搜索词!')
      }
      var search = throttle(getKeys, 500)
    </script>
  </body>
</html>

表单提交按钮未使用防抖效果(注意:这里将 alert 改成了控制台打印,因为 alert 是同步的,没法看效果):
JS防抖与节流_第1张图片
表单提交按钮使用防抖效果:

搜索框未使用节流效果(可以看到每次输入一个值都触发搜索,输入多少个值就执行了多少次搜索,若调取接口,则会导致页面卡顿,影响性能):

搜索框使用节流效果(可以看到连续输入,会每隔一段时间执行一次搜索):

总结

手写防抖和节流的核心还是闭包和定时器的使用。
防抖就是将多次事件合并成一个事件,只执行最后一次。
节流就是控制高频率触发事件时执行的频率,每隔一段时间执行一次,时间之内触发,忽略不去执行。

你可能感兴趣的:(js相关知识点,javascript,前端,开发语言)