首页 > 技术文章 > js函数防抖和函数节流

ahaMOMO 2020-01-19 17:28 原文

参考链接:https://juejin.im/post/5b651dc15188251aa30c8669

参考链接:https://www.jb51.net/article/158818.htm

在我们前端开发中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数。

通常这种情况下我们怎么去解决的呢?

一般来讲,防抖和节流是比较好的解决方案。

函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。

函数防抖

 

定义:就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。举个例子,当你在页面中使用onkeyUp监听用户在input框中的输入,如果用户按住一个6不放,那监听事件岂不是一直被触发,这样就浪费了一部分性能了,那么我们在一定事件内监听,也就是说我过了一秒再来看看你输入了多少个6,那这样是不是轻松多了。

 

原理:维护一个计时器,规定在延时时间后触发函数,但是在延时时间内再次被触发的话,就取消之前的计时器而重新设置,这样就能够保证只有最后一次操作被触发。即将所有操作合并为一个操作进行,并且只有最后一次操作是有效操作。

防抖函数分为非立即执行版和立即执行版。

非立即执行版:

触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>防抖</title>
</head>
<body>
 <button id="debounce">防抖,防抖,防抖</button>
 <script>
 window.onload = function () {
  let obtn = document.getElementById('debounce'); //获取按钮
 obtn.addEventListener('click',debounceHandle(debounce,500),false); //监听绑定事件
 }
 
 //防抖函数
function debounceHandle(func, delay) {
  let timer = null;
  return function(...args) {
    if (timer) clearTimeout(timer);//如果存在事件就清除定时器
    timer = setTimeout(() => {//如果不存在那么就开启定时器
      func.apply(this, args);
    }, delay);
  };
};
 
 //执行函数
 function debounce() {
  console.log('防抖,这里可以写一些防抖函数,如img中的onload事件');
 }
 </script>
</body>
</html>

立即执行版:

触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>防抖</title>
</head>
<body>
 <button id="debounce">防抖,防抖,防抖</button>
 <script>
 window.onload = function () {
  let obtn = document.getElementById('debounce'); //获取按钮
 obtn.addEventListener('click',debounceHandle(debounce,500),false); //监听绑定事件
 }
 
 //防抖函数
function debounceHandle(func, delay) {
    let timer = null;
    return function(...args) {
      if (timer) clearTimeout(timer);
      let callNow = !timer;
      timer = setTimeout(() => {
        timer = null;
      }, delay);
      if(callNow) func.apply(this, args);
    };
};
 
 //执行函数
 function debounce() {
  console.log('防抖,这里可以写一些防抖函数,如img中的onload事件');
 }
 </script>
</body>
</html>

上述防抖函数的代码还需要注意的是 this 和 参数的传递。是为了让 debounceHandle 函数最终返回的函数 this 指向不变以及依旧能接受到 e 参数。

函数节流

定义:当持续触发事件时,保证一定时间段内只调用一次事件处理函数,按照一定的规律在某个时间间隔内去处理函数。假如在一个页面中有任意多张图片,那么就有可能会使用懒加载技术,譬如图片的懒加载,我希望在下滑过程中图片不断的被加载出来,而不是只有当我停止下滑时候,图片才被加载出来。那么节流就是在一定时间间隔内触发一次事件。

原理:原理是通过判断是否达到一定时间来触发函数,使得一定时间内只触发一次函数。

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>节流</title>
 <style>
 div {
  height: 5000px;
 }
 </style>
</head>
<body>
 <div>节流,节流,节流</div>
 <script>
 window.onload = function () {
  window.addEventListener('scroll',throttleHandle(throttle),false); //监听绑定事件
 }
 
 //节流函数
 function throttleHandle (fn) {
  let timer = null,
   booleanVal = true; // 声明一个变量标志做判断
  return function () {
   if (!booleanVal) {
   return
   } //如果事件正在执行,那么就返回,将布尔值改为false
   booleanVal = false;
   //事件未执行,创建事件
   timer = setTimeout(function() {
   fn.apply(this,arguments);
   booleanVal = true; //事件执行完将布尔值改回
   },300)
  }
 }
 
 //执行函数
 function throttle() {
  var scrollNum = document.documentElement.scrollTop || document.body.scrollTop;
  console.log(scrollNum);
 }
 </script>
</body>
</html>

  

 

 

  

推荐阅读