欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  web前端

js高性能函数防抖与节流详解

程序员文章站 2022-04-04 19:58:02
...
函数节流是指一定时间内js方法只跑一次,函数防抖:是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。本文主要和大家分享js高性能函数防抖与节流详解,希望能帮助到大家。

一.函数节流(throttle)

1.函数节流的目的
例如,DOM 操作比起非DOM 交互需要更多的内存和CPU时间。连续尝试进行过多的DOM 相关操作可能会导致浏览器挂起,有时候甚至会崩溃。尤其在IE 中使用onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize 事件处理程序内部如果尝试进行DOM 操作,其高频率的更改可能会让浏览器崩溃。又例如,我们常见的一个搜索的功能,我们一般是绑定keyup事件,每按下一次键盘就搜索一次。但是我们的目的主要是每输入一些内容搜索一次而已。为了解决这些问题,就可以使用定时器对函数进行节流。
2.函数节流的原理
某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。

3.函数节流的基本模式

var processor = {
   timeoutId: null,
     //实际进行处理的方法
   performProcessing: function(){
     //实际执行的代码
   },
  //初始处理调用的方法
  process: function(){
    clearTimeout(this.timeoutId);
    var that = this;
    this.timeoutId = setTimeout(function(){
      that.performProcessing();
    }, 100);
  }
};
//尝试开始执行
processor.process();

4.列子

<!DOCTYPE html>
<html lang="zh-CN">
<head>  
	<meta charset="utf-8">
    <title></title>  
</head>  
<body>  	
	<input id="search" type="text" name="search">
<script>

	function queryData(text){
	  console.log("搜索:" + text);
	}
	var input = document.getElementById("search");
	input.addEventListener("keyup", function(event){
	  	throttle(queryData, null,500,this.value,1000);
	});
	        
function throttle(fn,context,delay,text,mustApplyTime){
  clearTimeout(fn.timer);
  fn._cur=Date.now();  //记录当前时间
 
  if(!fn._start){      //若该函数是第一次调用,则直接设置_start,即开始时间,为_cur,即此刻的时间
    fn._start=fn._cur;
  }
  if(fn._cur-fn._start>mustApplyTime){        //当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器
     fn.call(context,text);
     fn._start=fn._cur;
  }else{
    fn.timer=setTimeout(function(){
    fn.call(context,text);
    },delay);
  }
}
</script>
</body>  
</html>

JavaScript 节流函数 Throttle 详解

谈谈JS中的函数节流

二.函数防抖(debounce)

在解释这个函数前,我们先看下例子:注册页面,需要验证电话号码。此时我们可能想到的做法就是监听keypress事件,然后异验证。这个方法本身是没错的,但是如果用户快速的输入了一连串的手机号码,那么就会在瞬间触发了11次的请求,这无疑不是我们想要的。我们想要的是用户停止输入的时候才去触发验证的请求,这时候函数防抖可以帮到我们。

function debounce(func, wait, immediate) {
    var timeout; // 持久化一个定时器
     // 闭包函数可以访问timeout
    return function() {
    	 // 通过 this 和 arguments 获得函数的作用域和参数
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout); // 如果事件被触发,清除timer并重新开始计时
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

参数function是需要进行函数防抖的函数;参数wait则是需要等待的时间,单位为毫秒;immediate参数如果为true,则debounce函数会在调用时立刻执行一次function,而不需要等到wait这个时间后,例如防止点击提交按钮时的多次点击就可以使用这个参数。

列子:

<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>函数防抖与节流 </title>
</head>
<body>
	<form class="form-cnt" action="" method="">
			<input type="text" value="" id="tel"/>
	</form>
	<script type="text/javascript" src="js/jQuery-2.1.4.min.js" ></script>
<script>
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

function checkTel(){
	var val = $("#tel").val();  
	 var  re = new RegExp("(^1[3|4|5|7|8][0-9]{9}$)");  
	if(re.test(val)){  
	  console.log("结果:格式正确");  
	}else{  
	    console.log("结果:格式错误");  
	}  
}  
var lazyQuery = debounce(checkTel, 300);
$("#tel").on("keypress",lazyQuery);  
</script>
</body>
</html>

js高性能函数防抖与节流详解

这效果就看到触发了6次而不是11次

三.应用场景

(1).函数节流(throttle)
1. 频繁的mousemove/keydown,比如高频的鼠标移动,游戏射击类的
2. 搜索联想(keyup)
3. 进度条(我们可能不需要高频的更新进度)
4. 拖拽的dragover等
5. 高频的点击,抽奖等(哈哈,邪恶)

(2).函数防抖(debounce)
1. scroll/resize事件
2. 文本连续输入,ajax验证/关键字搜索

以上就是js高性能函数防抖与节流详解的详细内容,更多请关注其它相关文章!