JavsScript 节流函数 分金定穴

34 篇文章 0 订阅
21 篇文章 0 订阅

分金

节流函数,技术上最关键的地方有两点:

1、闭包保存了状态

2、apply的使用

定穴


Debounce
debounce	英[dɪ'baʊns]
美[dɪ'baʊns]
[词典]	[计] 防反跳;

口诀:设置一个锁,进门就关闭,干完再打开

的概念其实是从机械开关和继电器的“去弹跳”(debounce)衍生出来的概念。基本思路就是多个信号合并为一个信号。

在JavaScript中,debounce函数所做的事情,就是强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。我们希望在用户停止某个操作一段时间之后才执行响应的监听函数,而不是用户操作的过程当中,浏览器出发多少次时间,就执行多少次监听函数。

/***
 * 防抖函数
 * 每次事件,触发后,过指定时间(time)后执行,如果在在time时间内被触发,
 * 会从最近一次次触发的时间,再重新开始执行。
 * @param fn
 * @param time
 */
function debounce(fn,debounceHold = 200) {
  let time = null;
  
  return function () {
    let context = this;
    let args = arguments;
    
    clearTimeout(time);
    
    time = setTimeout(function () {
      // fn.apply(context,args);
      fn(args);
    },debounceHold);
  }
}

export default debounce;


Throttle
throttle	英[ˈθrɒtl]
美[ˈθrɑ:tl]
n.	节流阀; 喉咙,气管; [机] 风门;
vt.	扼杀,压制; 勒死,使窒息; 使节流; (用节汽阀等) 调节;
vi.	节流,减速; 窒息;

看字面意思就能理解大概,就是固定函数执行的速率,即所谓的节流。

正常情况下,mouseOver的监听函数可能会每20ms(假设)执行一次,如果设置200ms的“节流”,那么它就会每200ms执行一次。

/**
 * 节流函数
 * 控制函数触发的频率
 * @param fn
 * @param throttlehold
 * @returns {Function}
 */

function throttleV1(fn,throttlehold = 200) {
  var last;
  var time;
  
  return function () {
    var context = this;
    var args = arguments;
    
    var now = +new Date();
    
    if(last && now < last + throttlehold){
      clearTimeout(time);
      
      time = setTimeout(function () {
        last = now;
        fn.apply(context,args);
      },throttlehold);
  
      // 在时间区间的最开始和到达指定间隔的时候执行一次 fn
    }else{
      last = now;
      fn.apply(context,args);
    }
  }
}

Throttle改进版

相比而言,V2版本思路更加清晰。但是v1是第一次进来后立马执行,v2是只要进来,就会等待一段时间后再执行。所以导致了编程实现的过程完全不同。v1的如果实现v2的功能,就会很麻烦。

var throttleV2 = function(fn, delay, mustRunDelay){
 	var timer = null;
 	var t_start;
 	return function(){
 		var context = this, args = arguments, t_curr = +new Date();
 		clearTimeout(timer);
 		if(!t_start){
 			t_start = t_curr;
 		}
 		if(t_curr - t_start >= mustRunDelay){
 			fn.apply(context, args);
 			t_start = t_curr;
 		}
 		else {
 			timer = setTimeout(function(){
 				fn.apply(context, args);
 				t_start = t_curr;
 			}, delay);
 		}
 	};
 };

在这个拓展后的节流函数升级版,我们可以设置第三个参数,即必然触发执行的时间间隔。如果用下面的方法调用。

window.onresize = throttleV2(myFunc, 50, 100);

则意味着,50ms的间隔内连续触发的调用,后一个调用会把前一个调用的等待处理掉,但每隔100ms至少执行一次。原理也很简单,打时间tag,一开始记录第一次调用的时间戳,然后每次调用函数都去拿最新的时间跟记录时间比,超出给定的时间就执行一次,更新记录时间。

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值