您的当前位置:首页正文

防抖和节流函数详解(立即执行/非立即执行)

2024-12-02 来源:个人技术集锦

移动鼠标触发

1.防抖(立即执行/非立即执行)
  • 什么是防抖:一个事件在触发后,设置定时器,若n秒内该事件没有再次发生,那么执行这个函数,如果n秒内该事件再次发生了,那么定时器重新开始计时。
  • 应用
    • 每次 resize / scroll 触发统计事件
    • 文本输入的验证 (连续输入文字后发送AJAX请求进行验证,验证一次就好)
  • 1.1 非立即执行版
//防抖(非立即执行)
function debounce_1(fn,wait){
  var timerId = null;
  return function(){
  	var context = this
    var args = arguments
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      fn.apply(context,args)
    },wait)
  }
}
  • 1.2 立即执行版
//防抖(立即执行)
function debounce_2(fn,wait){
  var timerId = null;
  var flag = true;
  return function(){
  	var context = this
    var args = arguments
    clearTimeout(timerId);
    if(flag){
      fn.apply(context, args);
      flag = false
      }
    timerId = setTimeout(() => { flag = true},wait)
  }
}
  • 1.3 合并版
//防抖(合并版)
function debounce_merge(fn,wait = 500,isImmediate = false){
  var timerId = null;
  var flag = true;
  return function(){
    var context = this
    var args = arguments
    clearTimeout(timerId )
    if(isImmediate ){
        if(flag){
            fn.apply(context,args)
            flag = false
        }
        timerId = setTimeout(function(){
            flag = true
        },wait)
    }else{
        timerId = setTimeout(function(){
            fn.apply(context,args)
        },wait)
    }
  }
}
2.节流(立即执行/非立即执行)
  • 什么是节流:若一个函数在一段时间内持续高频触发,节流后将使得该函数在这段时间内每隔固定时间才执行一次
  • 应用
    • 与mousemove keyup/keydown 等相密切联系的函数
  • 2.1 非立即执行版
//定义函数
//节流(非立即执行)
function throttle_1(fn,wait){
  var flag = true;
  return function(){
  	var context = this
    var args = arguments
    if(flag){
      flag = false
      setTimeout(() => {
        fn.apply(context,args)
        flag = true
      },wait)
    }
  }
}
  • 2.2 立即执行版
//节流(立即执行)
function throttle_2(fn,wait){
  var flag = true;
  return function(){
  	var context = this
    var args = arguments
    if(flag) {
      fn.apply(context,args);
      flag = false;
      setTimeout(() => {
        flag = true
      },wait)
    }
  }
}
  • 2.3 合并版
//节流(合并)
function throttle_merge(fn,wait = 500,isImmediate = false){
  var flag = true;
  return function(){
    if(flag == true){
      var context = this
      var args = arguments
      flag = false
      isImmediate && fn.apply(context,args)
      setTimeout(() => {
        !isImmediate && fn.apply(context,args)
        flag = true
      },wait)
    }
  }
}
3.补充
  • 看文字远不如亲自操作了解得透彻,希望还不太明白的小伙伴在下面演示代码具体操作操作
  • 这里的几个函数都是使用的setTimeout来实现的,也可以使用 Date.now()来实现,思路一样,偷个懒就不写了,嘿嘿;
  • 合并版的 debounce(fn,wait,isImmediate) throttle(fn,wait,isImmediate)
4.演示代码

截图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    body{height: 1200px;}
  	div{width: 100%;background-color: lightcyan;overflow: hidden;}
	p{float: left;width: 10px;height:10px;background-color: pink;margin: 1px;}
  </style>
</head>
<body>
    防抖(非立即执行) <div id="d1_1"></div>
    防抖(立即执行) <div id="d1_2"></div>
    节流(非立即执行) <div id="d2_1"></div>
    节流(立即执行) <div id="d2_2"></div>
    <!-- 原生 <div id="d3"></div> -->
</body>
<script>
//防抖(非立即执行)
function debounce_1(fn,wait){
  var timerId = null;
  return function(){
    clearTimeout(timerId);
    timerId = setTimeout(() => {
      fn.apply(this,arguments)
    },wait)
  }
}
//防抖(立即执行)
function debounce_2(fn,wait){
  var timerId = null;
  var flag = true;
  return function(){
    clearTimeout(timerId);
    if(flag){
      fn.apply(this,arguments);
      flag = false
      }
    timerId = setTimeout(() => { flag = true},wait)
  }
}
//节流(非立即执行)
function throttle_1(fn,wait){
  var flag = true;
  return function(){
    if(flag == true){
      flag = false
      var timer = setTimeout(() => {
        fn.apply(this,arguments)
        flag = true
      },wait)
    }
  }
}
//节流(立即执行)
function throttle_2(fn,wait){
  var flag = true;
  var timer = null;
  return function(){
    if(flag) {
      fn.apply(this,arguments);
      flag = false;
      timer = setTimeout(() => {
        flag = true
      },wait)
    }
  }
}

//定义事件函数
function debounce_fn1(){ addElement(d1_1) }
function debounce_fn2(){ addElement(d1_2) }
function throttle_fn1(){ addElement(d2_1) }
function throttle_fn2(){ addElement(d2_2) }
// function origin(){ addElement(d3) }

//注册事件
var body = document.getElementsByTagName('body')[0]
body.addEventListener("mousemove",debounce_1(debounce_fn1,500))
body.addEventListener("mousemove",debounce_2(debounce_fn2,500))
body.addEventListener("mousemove",throttle_1(throttle_fn1,500))
body.addEventListener("mousemove",throttle_2(throttle_fn2,500))
// body.addEventListener("mousemove",origin)


//辅助函数
function addElement(f){
  var node=document.createElement("p");
	f.appendChild(node);
}
</script>
</html>
显示全文